Turbopack: Vc<T> and Turbo Engine type system improvements (#51792)
This is the Next.js side of https://github.com/vercel/turbo/pull/4587, which makes changes to Turbo Engine to allow expressing value cells as `Vc<Type>` instead of `TypeVc`, leveraging the type system to bring a slew of other improvements to writing Turbo Engine code. ## Turbopack updates * https://github.com/vercel/turbo/pull/4587
This commit is contained in:
parent
7ce663ed52
commit
5964b289e1
127 changed files with 4326 additions and 4239 deletions
71
Cargo.lock
generated
71
Cargo.lock
generated
|
@ -412,7 +412,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "auto-hash-map"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -3599,7 +3599,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "node-file-trace"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
|
@ -7259,9 +7259,10 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"auto-hash-map",
|
||||
"concurrent-queue",
|
||||
"dashmap",
|
||||
|
@ -7290,7 +7291,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks-build"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo-lock",
|
||||
|
@ -7302,7 +7303,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks-bytes"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
@ -7317,7 +7318,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks-env"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"dotenvs",
|
||||
|
@ -7331,7 +7332,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks-fetch"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indexmap",
|
||||
|
@ -7348,7 +7349,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks-fs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"auto-hash-map",
|
||||
|
@ -7378,7 +7379,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks-hash"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"base16",
|
||||
"hex",
|
||||
|
@ -7390,7 +7391,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks-macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"convert_case 0.6.0",
|
||||
|
@ -7404,7 +7405,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks-macros-shared"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -7414,7 +7415,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks-malloc"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"mimalloc",
|
||||
]
|
||||
|
@ -7422,7 +7423,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks-memory"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"auto-hash-map",
|
||||
|
@ -7445,7 +7446,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbo-tasks-testing"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"auto-hash-map",
|
||||
|
@ -7458,7 +7459,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
|
@ -7488,7 +7489,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-bench"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chromiumoxide",
|
||||
|
@ -7518,7 +7519,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-binding"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"auto-hash-map",
|
||||
"mdxjs",
|
||||
|
@ -7560,7 +7561,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-build"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indexmap",
|
||||
|
@ -7580,7 +7581,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-cli-utils"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.1.11",
|
||||
|
@ -7604,7 +7605,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-core"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -7632,7 +7633,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-create-test-app"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.1.11",
|
||||
|
@ -7645,7 +7646,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-css"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -7667,7 +7668,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-dev"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indexmap",
|
||||
|
@ -7691,7 +7692,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-dev-server"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-compression",
|
||||
|
@ -7727,7 +7728,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-ecmascript"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -7760,7 +7761,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-ecmascript-plugins"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -7783,7 +7784,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-ecmascript-runtime"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indoc",
|
||||
|
@ -7800,7 +7801,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-env"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indexmap",
|
||||
|
@ -7816,7 +7817,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-image"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.21.0",
|
||||
|
@ -7836,7 +7837,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-json"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
|
@ -7851,7 +7852,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-mdx"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"mdxjs",
|
||||
|
@ -7866,7 +7867,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-node"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
|
@ -7901,7 +7902,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-static"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
|
@ -7917,7 +7918,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-swc-utils"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"swc_core",
|
||||
"turbo-tasks",
|
||||
|
@ -7928,7 +7929,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "turbopack-test-utils"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917"
|
||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"once_cell",
|
||||
|
|
|
@ -44,11 +44,11 @@ swc_core = { version = "0.79.13" }
|
|||
testing = { version = "0.33.20" }
|
||||
|
||||
# Turbo crates
|
||||
turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230713.3" }
|
||||
turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230716.2" }
|
||||
# [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-230713.3" }
|
||||
turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230716.2" }
|
||||
# [TODO]: need to refactor embed_directory! macro usage in next-core
|
||||
turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230713.3" }
|
||||
turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230716.2" }
|
||||
|
||||
# General Deps
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@ use next_swc::{
|
|||
next_dynamic::next_dynamic,
|
||||
next_ssg::next_ssg,
|
||||
react_server_components::server_components,
|
||||
server_actions::{self, server_actions},
|
||||
server_actions::{
|
||||
server_actions, {self},
|
||||
},
|
||||
};
|
||||
use next_transform_font::{next_font_loaders, Config as FontLoaderConfig};
|
||||
use turbopack_binding::swc::{
|
||||
|
|
|
@ -9,7 +9,9 @@ use next_swc::{
|
|||
react_remove_properties::remove_properties,
|
||||
react_server_components::server_components,
|
||||
remove_console::remove_console,
|
||||
server_actions::{self, server_actions},
|
||||
server_actions::{
|
||||
server_actions, {self},
|
||||
},
|
||||
shake_exports::{shake_exports, Config as ShakeExportsConfig},
|
||||
};
|
||||
use next_transform_font::{next_font_loaders, Config as FontLoaderConfig};
|
||||
|
|
|
@ -7,17 +7,17 @@ use napi::{
|
|||
JsFunction,
|
||||
};
|
||||
use next_core::app_structure::{
|
||||
find_app_dir, get_entrypoints as get_entrypoints_impl, Components, ComponentsVc, Entrypoint,
|
||||
EntrypointsVc, LoaderTree, LoaderTreeVc, MetadataWithAltItem,
|
||||
find_app_dir, get_entrypoints as get_entrypoints_impl, Components, Entrypoint, Entrypoints,
|
||||
LoaderTree, MetadataWithAltItem,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turbo_tasks::{unit, ReadRef, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::{
|
||||
tasks::{
|
||||
debug::ValueDebugFormat, primitives::StringsVc, trace::TraceRawVcs, NothingVc,
|
||||
TryJoinIterExt, TurboTasks, ValueToString,
|
||||
debug::ValueDebugFormat, trace::TraceRawVcs, TryJoinIterExt, TurboTasks, ValueToString,
|
||||
},
|
||||
tasks_fs::{DiskFileSystemVc, FileSystem, FileSystemPathVc, FileSystemVc},
|
||||
tasks_fs::{DiskFileSystem, FileSystem, FileSystemPath},
|
||||
tasks_memory::MemoryBackend,
|
||||
},
|
||||
turbopack::core::PROJECT_FILESYSTEM_NAME,
|
||||
|
@ -26,20 +26,19 @@ use turbopack_binding::{
|
|||
use crate::register;
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn project_fs(project_dir: &str, watching: bool) -> Result<FileSystemVc> {
|
||||
let disk_fs =
|
||||
DiskFileSystemVc::new(PROJECT_FILESYSTEM_NAME.to_string(), project_dir.to_string());
|
||||
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());
|
||||
if watching {
|
||||
disk_fs.await?.start_watching_with_invalidation_reason()?;
|
||||
}
|
||||
Ok(disk_fs.into())
|
||||
Ok(Vc::upcast(disk_fs))
|
||||
}
|
||||
|
||||
#[turbo_tasks::value]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct LoaderTreeForJs {
|
||||
segment: String,
|
||||
parallel_routes: HashMap<String, LoaderTreeForJsReadRef>,
|
||||
parallel_routes: HashMap<String, ReadRef<LoaderTreeForJs>>,
|
||||
#[turbo_tasks(trace_ignore)]
|
||||
components: ComponentsForJs,
|
||||
}
|
||||
|
@ -47,8 +46,12 @@ struct LoaderTreeForJs {
|
|||
#[derive(PartialEq, Eq, Serialize, Deserialize, ValueDebugFormat, TraceRawVcs)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
enum EntrypointForJs {
|
||||
AppPage { loader_tree: LoaderTreeForJsReadRef },
|
||||
AppRoute { path: String },
|
||||
AppPage {
|
||||
loader_tree: ReadRef<LoaderTreeForJs>,
|
||||
},
|
||||
AppRoute {
|
||||
path: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(transparent)]
|
||||
|
@ -56,9 +59,12 @@ enum EntrypointForJs {
|
|||
struct EntrypointsForJs(HashMap<String, EntrypointForJs>);
|
||||
|
||||
#[turbo_tasks::value(transparent)]
|
||||
struct OptionEntrypointsForJs(Option<EntrypointsForJsVc>);
|
||||
struct OptionEntrypointsForJs(Option<Vc<EntrypointsForJs>>);
|
||||
|
||||
async fn fs_path_to_path(project_path: FileSystemPathVc, path: FileSystemPathVc) -> Result<String> {
|
||||
async fn fs_path_to_path(
|
||||
project_path: Vc<FileSystemPath>,
|
||||
path: Vc<FileSystemPath>,
|
||||
) -> Result<String> {
|
||||
match project_path.await?.get_path_to(&*path.await?) {
|
||||
None => Err(anyhow!(
|
||||
"Path {} is not inside of the project path {}",
|
||||
|
@ -119,8 +125,8 @@ enum MetadataForJsItem {
|
|||
}
|
||||
|
||||
async fn prepare_components_for_js(
|
||||
project_path: FileSystemPathVc,
|
||||
components: ComponentsVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
components: Vc<Components>,
|
||||
) -> Result<ComponentsForJs> {
|
||||
let Components {
|
||||
page,
|
||||
|
@ -136,8 +142,8 @@ async fn prepare_components_for_js(
|
|||
let mut result = ComponentsForJs::default();
|
||||
async fn add(
|
||||
result: &mut Option<String>,
|
||||
project_path: FileSystemPathVc,
|
||||
value: &Option<FileSystemPathVc>,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
value: &Option<Vc<FileSystemPath>>,
|
||||
) -> Result<()> {
|
||||
if let Some(value) = value {
|
||||
*result = Some(fs_path_to_path(project_path, *value).await?);
|
||||
|
@ -154,7 +160,7 @@ async fn prepare_components_for_js(
|
|||
add(&mut result.route, project_path, route).await?;
|
||||
async fn add_meta<'a>(
|
||||
meta: &mut Vec<MetadataForJsItem>,
|
||||
project_path: FileSystemPathVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
value: impl Iterator<Item = &'a MetadataWithAltItem>,
|
||||
) -> Result<()> {
|
||||
let mut value = value.peekable();
|
||||
|
@ -198,9 +204,9 @@ async fn prepare_components_for_js(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
async fn prepare_loader_tree_for_js(
|
||||
project_path: FileSystemPathVc,
|
||||
loader_tree: LoaderTreeVc,
|
||||
) -> Result<LoaderTreeForJsVc> {
|
||||
project_path: Vc<FileSystemPath>,
|
||||
loader_tree: Vc<LoaderTree>,
|
||||
) -> Result<Vc<LoaderTreeForJs>> {
|
||||
let LoaderTree {
|
||||
segment,
|
||||
parallel_routes,
|
||||
|
@ -229,9 +235,9 @@ async fn prepare_loader_tree_for_js(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
async fn prepare_entrypoints_for_js(
|
||||
project_path: FileSystemPathVc,
|
||||
entrypoints: EntrypointsVc,
|
||||
) -> Result<EntrypointsForJsVc> {
|
||||
project_path: Vc<FileSystemPath>,
|
||||
entrypoints: Vc<Entrypoints>,
|
||||
) -> Result<Vc<EntrypointsForJs>> {
|
||||
let entrypoints = entrypoints
|
||||
.await?
|
||||
.iter()
|
||||
|
@ -253,24 +259,24 @@ async fn prepare_entrypoints_for_js(
|
|||
.await?
|
||||
.into_iter()
|
||||
.collect();
|
||||
Ok(EntrypointsForJsVc::cell(entrypoints))
|
||||
Ok(Vc::cell(entrypoints))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn get_value(
|
||||
root_dir: &str,
|
||||
project_dir: &str,
|
||||
root_dir: String,
|
||||
project_dir: String,
|
||||
page_extensions: Vec<String>,
|
||||
watching: bool,
|
||||
) -> Result<OptionEntrypointsForJsVc> {
|
||||
let page_extensions = StringsVc::cell(page_extensions);
|
||||
let fs = project_fs(root_dir, watching);
|
||||
let project_relative = project_dir.strip_prefix(root_dir).unwrap();
|
||||
) -> 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_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);
|
||||
|
||||
let app_dir = find_app_dir(project_path);
|
||||
|
||||
|
@ -283,7 +289,7 @@ async fn get_value(
|
|||
None
|
||||
};
|
||||
|
||||
Ok(OptionEntrypointsForJsVc::cell(result))
|
||||
Ok(Vc::cell(result))
|
||||
}
|
||||
|
||||
#[napi]
|
||||
|
@ -295,7 +301,7 @@ pub fn stream_entrypoints(
|
|||
func: JsFunction,
|
||||
) -> napi::Result<()> {
|
||||
register();
|
||||
let func: ThreadsafeFunction<Option<EntrypointsForJsReadRef>, ErrorStrategy::CalleeHandled> =
|
||||
let func: ThreadsafeFunction<Option<ReadRef<EntrypointsForJs>>, ErrorStrategy::CalleeHandled> =
|
||||
func.create_threadsafe_function(0, |ctx| {
|
||||
let value = ctx.value;
|
||||
let value = serde_json::to_value(value)?;
|
||||
|
@ -305,16 +311,14 @@ pub fn stream_entrypoints(
|
|||
let project_dir = Arc::new(project_dir);
|
||||
let page_extensions = Arc::new(page_extensions);
|
||||
turbo_tasks.spawn_root_task(move || {
|
||||
let func: ThreadsafeFunction<
|
||||
Option<turbo_tasks::ReadRef<EntrypointsForJs, HashMap<String, EntrypointForJs>>>,
|
||||
> = func.clone();
|
||||
let func: ThreadsafeFunction<Option<ReadRef<EntrypointsForJs>>> = func.clone();
|
||||
let project_dir = project_dir.clone();
|
||||
let root_dir = root_dir.clone();
|
||||
let page_extensions: Arc<Vec<String>> = page_extensions.clone();
|
||||
Box::pin(async move {
|
||||
if let Some(entrypoints) = &*get_value(
|
||||
&root_dir,
|
||||
&project_dir,
|
||||
(*root_dir).clone(),
|
||||
(*project_dir).clone(),
|
||||
page_extensions.iter().map(|s| s.to_string()).collect(),
|
||||
true,
|
||||
)
|
||||
|
@ -328,7 +332,7 @@ pub fn stream_entrypoints(
|
|||
func.call(Ok(None), ThreadsafeFunctionCallMode::NonBlocking);
|
||||
}
|
||||
|
||||
Ok(NothingVc::new().into())
|
||||
Ok(unit().node)
|
||||
})
|
||||
});
|
||||
Ok(())
|
||||
|
@ -345,8 +349,8 @@ 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,
|
||||
root_dir,
|
||||
project_dir,
|
||||
page_extensions.iter().map(|s| s.to_string()).collect(),
|
||||
false,
|
||||
)
|
||||
|
|
|
@ -28,6 +28,8 @@ DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#![recursion_limit = "2048"]
|
||||
//#![deny(clippy::all)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(async_fn_in_trait)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate napi_derive;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use napi::{bindgen_prelude::External, JsFunction};
|
||||
use next_api::route::{Endpoint, EndpointVc, WrittenEndpoint};
|
||||
use next_api::route::{Endpoint, WrittenEndpoint};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::core::error::PrettyPrintError;
|
||||
|
||||
use super::utils::{subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc};
|
||||
|
@ -23,12 +26,28 @@ impl From<&WrittenEndpoint> for NapiWrittenEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE(alexkirsz) We go through an extra layer of indirection here because of
|
||||
// two factors:
|
||||
// 1. rustc currently has a bug where using a dyn trait as a type argument to
|
||||
// some async functions (in this case `endpoint_write_to_disk`) can cause
|
||||
// higher-ranked lifetime errors. See https://github.com/rust-lang/rust/issues/102211
|
||||
// 2. the type_complexity clippy lint.
|
||||
pub struct ExternalEndpoint(pub VcArc<Vc<Box<dyn Endpoint>>>);
|
||||
|
||||
impl Deref for ExternalEndpoint {
|
||||
type Target = VcArc<Vc<Box<dyn Endpoint>>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub async fn endpoint_write_to_disk(
|
||||
#[napi(ts_arg_type = "{ __napiType: \"Endpoint\" }")] endpoint: External<VcArc<EndpointVc>>,
|
||||
#[napi(ts_arg_type = "{ __napiType: \"Endpoint\" }")] endpoint: External<ExternalEndpoint>,
|
||||
) -> napi::Result<NapiWrittenEndpoint> {
|
||||
let turbo_tasks = endpoint.turbo_tasks().clone();
|
||||
let endpoint = **endpoint;
|
||||
let endpoint = ***endpoint;
|
||||
let written = turbo_tasks
|
||||
.run_once(async move { endpoint.write_to_disk().strongly_consistent().await })
|
||||
.await
|
||||
|
@ -39,7 +58,9 @@ pub async fn endpoint_write_to_disk(
|
|||
|
||||
#[napi(ts_return_type = "{ __napiType: \"RootTask\" }")]
|
||||
pub fn endpoint_changed_subscribe(
|
||||
#[napi(ts_arg_type = "{ __napiType: \"Endpoint\" }")] endpoint: External<VcArc<EndpointVc>>,
|
||||
#[napi(ts_arg_type = "{ __napiType: \"Endpoint\" }")] endpoint: External<
|
||||
VcArc<Vc<Box<dyn Endpoint>>>,
|
||||
>,
|
||||
func: JsFunction,
|
||||
) -> napi::Result<External<RootTask>> {
|
||||
let turbo_tasks = endpoint.turbo_tasks().clone();
|
||||
|
|
|
@ -3,15 +3,18 @@ use std::sync::Arc;
|
|||
use anyhow::Result;
|
||||
use napi::{bindgen_prelude::External, JsFunction};
|
||||
use next_api::{
|
||||
project::{Middleware, ProjectOptions, ProjectVc},
|
||||
route::{EndpointVc, Route},
|
||||
project::{Middleware, Project, ProjectOptions},
|
||||
route::{Endpoint, Route},
|
||||
};
|
||||
use turbo_tasks::TurboTasks;
|
||||
use turbo_tasks::{TurboTasks, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_memory::MemoryBackend, turbopack::core::error::PrettyPrintError,
|
||||
};
|
||||
|
||||
use super::utils::{serde_enum_to_string, subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc};
|
||||
use super::{
|
||||
endpoint::ExternalEndpoint,
|
||||
utils::{serde_enum_to_string, subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc},
|
||||
};
|
||||
use crate::register;
|
||||
|
||||
#[napi(object)]
|
||||
|
@ -46,7 +49,9 @@ impl From<NapiProjectOptions> for ProjectOptions {
|
|||
}
|
||||
|
||||
#[napi(ts_return_type = "{ __napiType: \"Project\" }")]
|
||||
pub async fn project_new(options: NapiProjectOptions) -> napi::Result<External<VcArc<ProjectVc>>> {
|
||||
pub async fn project_new(
|
||||
options: NapiProjectOptions,
|
||||
) -> napi::Result<External<VcArc<Vc<Project>>>> {
|
||||
register();
|
||||
let turbo_tasks = TurboTasks::new(MemoryBackend::new(
|
||||
options
|
||||
|
@ -56,7 +61,7 @@ pub async fn project_new(options: NapiProjectOptions) -> napi::Result<External<V
|
|||
));
|
||||
let options = options.into();
|
||||
let project = turbo_tasks
|
||||
.run_once(async move { ProjectVc::new(options).resolve().await })
|
||||
.run_once(async move { Project::new(options).resolve().await })
|
||||
.await
|
||||
.map_err(|e| napi::Error::from_reason(PrettyPrintError(&e).to_string()))?;
|
||||
Ok(External::new_with_size_hint(
|
||||
|
@ -75,10 +80,10 @@ struct NapiRoute {
|
|||
pub r#type: &'static str,
|
||||
|
||||
// Different representations of the endpoint
|
||||
pub endpoint: Option<External<VcArc<EndpointVc>>>,
|
||||
pub html_endpoint: Option<External<VcArc<EndpointVc>>>,
|
||||
pub rsc_endpoint: Option<External<VcArc<EndpointVc>>>,
|
||||
pub data_endpoint: Option<External<VcArc<EndpointVc>>>,
|
||||
pub endpoint: Option<External<ExternalEndpoint>>,
|
||||
pub html_endpoint: Option<External<ExternalEndpoint>>,
|
||||
pub rsc_endpoint: Option<External<ExternalEndpoint>>,
|
||||
pub data_endpoint: Option<External<ExternalEndpoint>>,
|
||||
}
|
||||
|
||||
impl NapiRoute {
|
||||
|
@ -87,8 +92,12 @@ impl NapiRoute {
|
|||
value: Route,
|
||||
turbo_tasks: &Arc<TurboTasks<MemoryBackend>>,
|
||||
) -> Self {
|
||||
let convert_endpoint =
|
||||
|endpoint: EndpointVc| Some(External::new(VcArc::new(turbo_tasks.clone(), endpoint)));
|
||||
let convert_endpoint = |endpoint: Vc<Box<dyn Endpoint>>| {
|
||||
Some(External::new(ExternalEndpoint(VcArc::new(
|
||||
turbo_tasks.clone(),
|
||||
endpoint,
|
||||
))))
|
||||
};
|
||||
match value {
|
||||
Route::Page {
|
||||
html_endpoint,
|
||||
|
@ -133,7 +142,7 @@ impl NapiRoute {
|
|||
|
||||
#[napi(object)]
|
||||
struct NapiMiddleware {
|
||||
pub endpoint: External<VcArc<EndpointVc>>,
|
||||
pub endpoint: External<VcArc<Vc<Box<dyn Endpoint>>>>,
|
||||
pub runtime: String,
|
||||
pub matcher: Option<Vec<String>>,
|
||||
}
|
||||
|
@ -161,7 +170,7 @@ struct NapiEntrypoints {
|
|||
|
||||
#[napi(ts_return_type = "{ __napiType: \"RootTask\" }")]
|
||||
pub fn project_entrypoints_subscribe(
|
||||
#[napi(ts_arg_type = "{ __napiType: \"Project\" }")] project: External<VcArc<ProjectVc>>,
|
||||
#[napi(ts_arg_type = "{ __napiType: \"Project\" }")] project: External<VcArc<Vc<Project>>>,
|
||||
func: JsFunction,
|
||||
) -> napi::Result<External<RootTask>> {
|
||||
let turbo_tasks = project.turbo_tasks().clone();
|
||||
|
|
|
@ -7,7 +7,7 @@ use napi::{
|
|||
JsFunction, JsObject, NapiRaw, NapiValue, Status,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use turbo_tasks::{NothingVc, TaskId, TurboTasks};
|
||||
use turbo_tasks::{unit, TaskId, TurboTasks};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_memory::MemoryBackend, turbopack::core::error::PrettyPrintError,
|
||||
};
|
||||
|
@ -127,7 +127,7 @@ pub fn subscribe<T: 'static + Send + Sync, F: Future<Output = Result<T>> + Send,
|
|||
eprintln!("{}", error);
|
||||
return Err(error);
|
||||
}
|
||||
Ok(NothingVc::new().into())
|
||||
Ok(unit().node)
|
||||
})
|
||||
});
|
||||
Ok(External::new(RootTask {
|
||||
|
|
|
@ -31,7 +31,13 @@ use std::{cell::RefCell, env, path::PathBuf};
|
|||
use anyhow::anyhow;
|
||||
use napi::bindgen_prelude::{External, Status};
|
||||
#[cfg(feature = "crash-report")]
|
||||
use sentry::{init, types::Dsn, ClientInitGuard, ClientOptions};
|
||||
use sentry::init;
|
||||
#[cfg(feature = "crash-report")]
|
||||
use sentry::types::Dsn;
|
||||
#[cfg(feature = "crash-report")]
|
||||
use sentry::ClientInitGuard;
|
||||
#[cfg(feature = "crash-report")]
|
||||
use sentry::ClientOptions;
|
||||
use tracing_chrome::{ChromeLayerBuilder, FlushGuard};
|
||||
use tracing_subscriber::{filter, prelude::*, util::SubscriberInitExt, Layer};
|
||||
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
use next_core::app_structure::Entrypoint;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turbo_tasks::{trace::TraceRawVcs, CompletionVc};
|
||||
use turbo_tasks::{trace::TraceRawVcs, Completion, Vc};
|
||||
|
||||
use crate::route::{Endpoint, EndpointVc, Route, RouteVc, WrittenEndpointVc};
|
||||
use crate::route::{Endpoint, Route, WrittenEndpoint};
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn app_entry_point_to_route(entrypoint: Entrypoint) -> RouteVc {
|
||||
pub async fn app_entry_point_to_route(entrypoint: Entrypoint) -> Vc<Route> {
|
||||
match entrypoint {
|
||||
Entrypoint::AppPage { .. } => Route::AppPage {
|
||||
html_endpoint: AppPageEndpoint {
|
||||
ty: AppPageEndpointType::Html,
|
||||
}
|
||||
.cell()
|
||||
.into(),
|
||||
rsc_endpoint: AppPageEndpoint {
|
||||
ty: AppPageEndpointType::Rsc,
|
||||
}
|
||||
.cell()
|
||||
.into(),
|
||||
html_endpoint: Vc::upcast(
|
||||
AppPageEndpoint {
|
||||
ty: AppPageEndpointType::Html,
|
||||
}
|
||||
.cell(),
|
||||
),
|
||||
rsc_endpoint: Vc::upcast(
|
||||
AppPageEndpoint {
|
||||
ty: AppPageEndpointType::Rsc,
|
||||
}
|
||||
.cell(),
|
||||
),
|
||||
},
|
||||
Entrypoint::AppRoute { .. } => Route::AppRoute {
|
||||
endpoint: AppRouteEndpoint.cell().into(),
|
||||
endpoint: Vc::upcast(AppRouteEndpoint.cell()),
|
||||
},
|
||||
}
|
||||
.cell()
|
||||
|
@ -40,12 +42,12 @@ struct AppPageEndpoint {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Endpoint for AppPageEndpoint {
|
||||
#[turbo_tasks::function]
|
||||
fn write_to_disk(&self) -> WrittenEndpointVc {
|
||||
fn write_to_disk(&self) -> Vc<WrittenEndpoint> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn changed(&self) -> CompletionVc {
|
||||
fn changed(&self) -> Vc<Completion> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -56,12 +58,12 @@ struct AppRouteEndpoint;
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Endpoint for AppRouteEndpoint {
|
||||
#[turbo_tasks::function]
|
||||
fn write_to_disk(&self) -> WrittenEndpointVc {
|
||||
fn write_to_disk(&self) -> Vc<WrittenEndpoint> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn changed(&self) -> CompletionVc {
|
||||
fn changed(&self) -> Vc<Completion> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![feature(future_join)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(async_fn_in_trait)]
|
||||
|
||||
mod app;
|
||||
mod pages;
|
||||
|
|
|
@ -2,45 +2,42 @@ use anyhow::{bail, Context, Result};
|
|||
use indexmap::IndexMap;
|
||||
use next_core::{
|
||||
create_page_loader_entry_module, emit_all_assets, get_asset_path_from_pathname,
|
||||
pages_structure::{
|
||||
PagesDirectoryStructure, PagesDirectoryStructureVc, PagesStructure, PagesStructureItem,
|
||||
PagesStructureVc,
|
||||
},
|
||||
pages_structure::{PagesDirectoryStructure, PagesStructure, PagesStructureItem},
|
||||
};
|
||||
use turbo_tasks::{primitives::StringVc, CompletionVc, CompletionsVc, Value};
|
||||
use turbo_tasks::{Completion, Completions, Value, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::FileSystemPathVc,
|
||||
turbo::tasks_fs::FileSystemPath,
|
||||
turbopack::{
|
||||
core::{
|
||||
asset::Asset,
|
||||
changed::{any_content_changed, any_content_changed_of_output_assets},
|
||||
chunk::{ChunkableModule, ChunkingContext},
|
||||
context::AssetContext,
|
||||
file_source::FileSourceVc,
|
||||
output::{OutputAssetVc, OutputAssetsVc},
|
||||
file_source::FileSource,
|
||||
output::{OutputAsset, OutputAssets},
|
||||
reference_type::{EntryReferenceSubType, ReferenceType},
|
||||
source::SourceVc,
|
||||
source::Source,
|
||||
},
|
||||
ecmascript::EcmascriptModuleAssetVc,
|
||||
ecmascript::EcmascriptModuleAsset,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
project::ProjectVc,
|
||||
route::{Endpoint, EndpointVc, Route, RoutesVc, WrittenEndpoint, WrittenEndpointVc},
|
||||
project::Project,
|
||||
route::{Endpoint, Route, Routes, WrittenEndpoint},
|
||||
};
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_pages_routes(
|
||||
project: ProjectVc,
|
||||
page_structure: PagesStructureVc,
|
||||
) -> Result<RoutesVc> {
|
||||
project: Vc<Project>,
|
||||
page_structure: Vc<PagesStructure>,
|
||||
) -> Result<Vc<Routes>> {
|
||||
let PagesStructure { api, pages, .. } = *page_structure.await?;
|
||||
let mut routes = IndexMap::new();
|
||||
async fn add_dir_to_routes(
|
||||
routes: &mut IndexMap<String, Route>,
|
||||
dir: PagesDirectoryStructureVc,
|
||||
make_route: impl Fn(StringVc, StringVc, FileSystemPathVc) -> Route,
|
||||
dir: Vc<PagesDirectoryStructure>,
|
||||
make_route: impl Fn(Vc<String>, Vc<String>, Vc<FileSystemPath>) -> Route,
|
||||
) -> Result<()> {
|
||||
let mut queue = vec![dir];
|
||||
while let Some(dir) = queue.pop() {
|
||||
|
@ -57,8 +54,8 @@ pub async fn get_pages_routes(
|
|||
original_path,
|
||||
} = *item.await?;
|
||||
let pathname = format!("/{}", next_router_path.await?.path);
|
||||
let pathname_vc = StringVc::cell(pathname.clone());
|
||||
let original_name = StringVc::cell(format!("/{}", original_path.await?.path));
|
||||
let pathname_vc = Vc::cell(pathname.clone());
|
||||
let original_name = Vc::cell(format!("/{}", original_path.await?.path));
|
||||
let route = make_route(pathname_vc, original_name, project_path);
|
||||
routes.insert(pathname, route);
|
||||
}
|
||||
|
@ -71,7 +68,7 @@ pub async fn get_pages_routes(
|
|||
if let Some(api) = api {
|
||||
add_dir_to_routes(&mut routes, api, |pathname, original_name, path| {
|
||||
Route::PageApi {
|
||||
endpoint: ApiEndpointVc::new(project, pathname, original_name, path).into(),
|
||||
endpoint: Vc::upcast(ApiEndpoint::new(project, pathname, original_name, path)),
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
|
@ -79,34 +76,42 @@ pub async fn get_pages_routes(
|
|||
if let Some(page) = pages {
|
||||
add_dir_to_routes(&mut routes, page, |pathname, original_name, path| {
|
||||
Route::Page {
|
||||
html_endpoint: PageHtmlEndpointVc::new(project, pathname, original_name, path)
|
||||
.into(),
|
||||
data_endpoint: PageDataEndpointVc::new(project, pathname, original_name, path)
|
||||
.into(),
|
||||
html_endpoint: Vc::upcast(PageHtmlEndpoint::new(
|
||||
project,
|
||||
pathname,
|
||||
original_name,
|
||||
path,
|
||||
)),
|
||||
data_endpoint: Vc::upcast(PageDataEndpoint::new(
|
||||
project,
|
||||
pathname,
|
||||
original_name,
|
||||
path,
|
||||
)),
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
Ok(RoutesVc::cell(routes))
|
||||
Ok(Vc::cell(routes))
|
||||
}
|
||||
|
||||
#[turbo_tasks::value]
|
||||
struct PageHtmlEndpoint {
|
||||
project: ProjectVc,
|
||||
pathname: StringVc,
|
||||
original_name: StringVc,
|
||||
path: FileSystemPathVc,
|
||||
project: Vc<Project>,
|
||||
pathname: Vc<String>,
|
||||
original_name: Vc<String>,
|
||||
path: Vc<FileSystemPath>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl PageHtmlEndpointVc {
|
||||
impl PageHtmlEndpoint {
|
||||
#[turbo_tasks::function]
|
||||
fn new(
|
||||
project: ProjectVc,
|
||||
pathname: StringVc,
|
||||
original_name: StringVc,
|
||||
path: FileSystemPathVc,
|
||||
) -> Self {
|
||||
project: Vc<Project>,
|
||||
pathname: Vc<String>,
|
||||
original_name: Vc<String>,
|
||||
path: Vc<FileSystemPath>,
|
||||
) -> Vc<Self> {
|
||||
PageHtmlEndpoint {
|
||||
project,
|
||||
pathname,
|
||||
|
@ -117,13 +122,13 @@ impl PageHtmlEndpointVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn source(self) -> Result<SourceVc> {
|
||||
async fn source(self: Vc<Self>) -> Result<Vc<Box<dyn Source>>> {
|
||||
let this = self.await?;
|
||||
Ok(FileSourceVc::new(this.path).into())
|
||||
Ok(Vc::upcast(FileSource::new(this.path)))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn client_chunks(self) -> Result<OutputAssetsVc> {
|
||||
async fn client_chunks(self: Vc<Self>) -> Result<Vc<OutputAssets>> {
|
||||
let this = self.await?;
|
||||
|
||||
let client_module = create_page_loader_entry_module(
|
||||
|
@ -132,27 +137,28 @@ impl PageHtmlEndpointVc {
|
|||
this.pathname,
|
||||
);
|
||||
|
||||
let Some(client_module) = EcmascriptModuleAssetVc::resolve_from(client_module).await?
|
||||
let Some(client_module) =
|
||||
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(client_module).await?
|
||||
else {
|
||||
bail!("expected an ECMAScript module asset");
|
||||
};
|
||||
|
||||
let client_chunking_context = this.project.client_chunking_context();
|
||||
|
||||
let client_entry_chunk = client_module.as_root_chunk(client_chunking_context.into());
|
||||
let client_entry_chunk = client_module.as_root_chunk(Vc::upcast(client_chunking_context));
|
||||
|
||||
let client_chunks = client_chunking_context.evaluated_chunk_group(
|
||||
client_entry_chunk,
|
||||
this.project
|
||||
.pages_client_runtime_entries()
|
||||
.with_entry(client_module.into()),
|
||||
.with_entry(Vc::upcast(client_module)),
|
||||
);
|
||||
|
||||
Ok(client_chunks)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn ssr_chunk(self) -> Result<OutputAssetVc> {
|
||||
async fn ssr_chunk(self: Vc<Self>) -> Result<Vc<Box<dyn OutputAsset>>> {
|
||||
let this = self.await?;
|
||||
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
||||
|
||||
|
@ -161,17 +167,19 @@ impl PageHtmlEndpointVc {
|
|||
.pages_ssr_module_context()
|
||||
.process(self.source(), reference_type.clone());
|
||||
|
||||
let Some(ssr_module) = EcmascriptModuleAssetVc::resolve_from(ssr_module).await? else {
|
||||
let Some(ssr_module) =
|
||||
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(ssr_module).await?
|
||||
else {
|
||||
bail!("expected an ECMAScript module asset");
|
||||
};
|
||||
|
||||
let asset_path = get_asset_path_from_pathname(&this.pathname.await?, ".js");
|
||||
|
||||
let ssr_entry_chunk_path_string = format!("server/pages{asset_path}");
|
||||
let ssr_entry_chunk_path = this.project.node_root().join(&ssr_entry_chunk_path_string);
|
||||
let ssr_entry_chunk_path = this.project.node_root().join(ssr_entry_chunk_path_string);
|
||||
let ssr_entry_chunk = this.project.ssr_chunking_context().entry_chunk(
|
||||
ssr_entry_chunk_path,
|
||||
ssr_module.into(),
|
||||
Vc::upcast(ssr_module),
|
||||
this.project.pages_ssr_runtime_entries(),
|
||||
);
|
||||
|
||||
|
@ -182,19 +190,19 @@ impl PageHtmlEndpointVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Endpoint for PageHtmlEndpoint {
|
||||
#[turbo_tasks::function]
|
||||
async fn write_to_disk(self_vc: PageHtmlEndpointVc) -> Result<WrittenEndpointVc> {
|
||||
let this = self_vc.await?;
|
||||
let ssr_chunk = self_vc.ssr_chunk();
|
||||
async fn write_to_disk(self: Vc<Self>) -> Result<Vc<WrittenEndpoint>> {
|
||||
let this = self.await?;
|
||||
let ssr_chunk = self.ssr_chunk();
|
||||
let ssr_emit = emit_all_assets(
|
||||
OutputAssetsVc::cell(vec![ssr_chunk]),
|
||||
Vc::cell(vec![ssr_chunk]),
|
||||
this.project.node_root(),
|
||||
this.project.client_root().join("_next"),
|
||||
this.project.client_root().join("_next".to_string()),
|
||||
this.project.node_root(),
|
||||
);
|
||||
let client_emit = emit_all_assets(
|
||||
self_vc.client_chunks(),
|
||||
self.client_chunks(),
|
||||
this.project.node_root(),
|
||||
this.project.client_root().join("_next"),
|
||||
this.project.client_root().join("_next".to_string()),
|
||||
this.project.node_root(),
|
||||
);
|
||||
|
||||
|
@ -215,32 +223,32 @@ impl Endpoint for PageHtmlEndpoint {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn changed(self_vc: PageHtmlEndpointVc) -> CompletionVc {
|
||||
let ssr_chunk = self_vc.ssr_chunk();
|
||||
CompletionsVc::all(vec![
|
||||
any_content_changed(ssr_chunk.into()),
|
||||
any_content_changed_of_output_assets(self_vc.client_chunks()),
|
||||
fn changed(self: Vc<Self>) -> Vc<Completion> {
|
||||
let ssr_chunk = self.ssr_chunk();
|
||||
Completions::all(vec![
|
||||
any_content_changed(Vc::upcast(ssr_chunk)),
|
||||
any_content_changed_of_output_assets(self.client_chunks()),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value]
|
||||
struct PageDataEndpoint {
|
||||
project: ProjectVc,
|
||||
pathname: StringVc,
|
||||
original_name: StringVc,
|
||||
path: FileSystemPathVc,
|
||||
project: Vc<Project>,
|
||||
pathname: Vc<String>,
|
||||
original_name: Vc<String>,
|
||||
path: Vc<FileSystemPath>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl PageDataEndpointVc {
|
||||
impl PageDataEndpoint {
|
||||
#[turbo_tasks::function]
|
||||
fn new(
|
||||
project: ProjectVc,
|
||||
pathname: StringVc,
|
||||
original_name: StringVc,
|
||||
path: FileSystemPathVc,
|
||||
) -> Self {
|
||||
project: Vc<Project>,
|
||||
pathname: Vc<String>,
|
||||
original_name: Vc<String>,
|
||||
path: Vc<FileSystemPath>,
|
||||
) -> Vc<Self> {
|
||||
PageDataEndpoint {
|
||||
project,
|
||||
pathname,
|
||||
|
@ -251,13 +259,13 @@ impl PageDataEndpointVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn source(self) -> Result<SourceVc> {
|
||||
async fn source(self: Vc<Self>) -> Result<Vc<Box<dyn Source>>> {
|
||||
let this = self.await?;
|
||||
Ok(FileSourceVc::new(this.path).into())
|
||||
Ok(Vc::upcast(FileSource::new(this.path)))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn ssr_data_chunk(self) -> Result<OutputAssetVc> {
|
||||
async fn ssr_data_chunk(self: Vc<Self>) -> Result<Vc<Box<dyn OutputAsset>>> {
|
||||
let this = self.await?;
|
||||
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
||||
|
||||
|
@ -266,7 +274,8 @@ impl PageDataEndpointVc {
|
|||
.pages_ssr_data_module_context()
|
||||
.process(self.source(), reference_type.clone());
|
||||
|
||||
let Some(ssr_data_module) = EcmascriptModuleAssetVc::resolve_from(ssr_data_module).await?
|
||||
let Some(ssr_data_module) =
|
||||
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(ssr_data_module).await?
|
||||
else {
|
||||
bail!("expected an ECMAScript module asset");
|
||||
};
|
||||
|
@ -277,10 +286,10 @@ impl PageDataEndpointVc {
|
|||
let ssr_data_entry_chunk_path = this
|
||||
.project
|
||||
.node_root()
|
||||
.join(&ssr_data_entry_chunk_path_string);
|
||||
.join(ssr_data_entry_chunk_path_string);
|
||||
let ssr_data_entry_chunk = this.project.ssr_data_chunking_context().entry_chunk(
|
||||
ssr_data_entry_chunk_path,
|
||||
ssr_data_module.into(),
|
||||
Vc::upcast(ssr_data_module),
|
||||
this.project.pages_ssr_runtime_entries(),
|
||||
);
|
||||
|
||||
|
@ -291,13 +300,13 @@ impl PageDataEndpointVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Endpoint for PageDataEndpoint {
|
||||
#[turbo_tasks::function]
|
||||
async fn write_to_disk(self_vc: PageDataEndpointVc) -> Result<WrittenEndpointVc> {
|
||||
let this = self_vc.await?;
|
||||
let ssr_data_chunk = self_vc.ssr_data_chunk();
|
||||
async fn write_to_disk(self: Vc<Self>) -> Result<Vc<WrittenEndpoint>> {
|
||||
let this = self.await?;
|
||||
let ssr_data_chunk = self.ssr_data_chunk();
|
||||
emit_all_assets(
|
||||
OutputAssetsVc::cell(vec![ssr_data_chunk]),
|
||||
Vc::cell(vec![ssr_data_chunk]),
|
||||
this.project.node_root(),
|
||||
this.project.client_root().join("_next"),
|
||||
this.project.client_root().join("_next".to_string()),
|
||||
this.project.node_root(),
|
||||
)
|
||||
.await?;
|
||||
|
@ -316,29 +325,29 @@ impl Endpoint for PageDataEndpoint {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn changed(self_vc: PageDataEndpointVc) -> Result<CompletionVc> {
|
||||
let ssr_data_chunk = self_vc.ssr_data_chunk();
|
||||
Ok(any_content_changed(ssr_data_chunk.into()))
|
||||
async fn changed(self: Vc<Self>) -> Result<Vc<Completion>> {
|
||||
let ssr_data_chunk = self.ssr_data_chunk();
|
||||
Ok(any_content_changed(Vc::upcast(ssr_data_chunk)))
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value]
|
||||
struct ApiEndpoint {
|
||||
project: ProjectVc,
|
||||
pathname: StringVc,
|
||||
original_name: StringVc,
|
||||
path: FileSystemPathVc,
|
||||
project: Vc<Project>,
|
||||
pathname: Vc<String>,
|
||||
original_name: Vc<String>,
|
||||
path: Vc<FileSystemPath>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ApiEndpointVc {
|
||||
impl ApiEndpoint {
|
||||
#[turbo_tasks::function]
|
||||
fn new(
|
||||
project: ProjectVc,
|
||||
pathname: StringVc,
|
||||
original_name: StringVc,
|
||||
path: FileSystemPathVc,
|
||||
) -> Self {
|
||||
project: Vc<Project>,
|
||||
pathname: Vc<String>,
|
||||
original_name: Vc<String>,
|
||||
path: Vc<FileSystemPath>,
|
||||
) -> Vc<Self> {
|
||||
ApiEndpoint {
|
||||
project,
|
||||
pathname,
|
||||
|
@ -352,12 +361,12 @@ impl ApiEndpointVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Endpoint for ApiEndpoint {
|
||||
#[turbo_tasks::function]
|
||||
fn write_to_disk(&self) -> WrittenEndpointVc {
|
||||
fn write_to_disk(&self) -> Vc<WrittenEndpoint> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn changed(&self) -> CompletionVc {
|
||||
fn changed(&self) -> Vc<Completion> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,47 +10,45 @@ use next_core::{
|
|||
get_client_module_options_context, get_client_resolve_options_context,
|
||||
get_client_runtime_entries, ClientContextType,
|
||||
},
|
||||
next_config::NextConfigVc,
|
||||
next_dynamic::NextDynamicTransitionVc,
|
||||
next_config::NextConfig,
|
||||
next_dynamic::NextDynamicTransition,
|
||||
next_server::{
|
||||
get_server_chunking_context, get_server_compile_time_info,
|
||||
get_server_module_options_context, get_server_resolve_options_context,
|
||||
get_server_runtime_entries, ServerContextType,
|
||||
},
|
||||
pages_structure::{find_pages_structure, PagesStructureVc},
|
||||
pages_structure::{find_pages_structure, PagesStructure},
|
||||
util::NextSourceConfig,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turbo_tasks::{
|
||||
debug::ValueDebugFormat, trace::TraceRawVcs, NothingVc, TaskInput, TransientValue,
|
||||
TryJoinIterExt, Value,
|
||||
debug::ValueDebugFormat, trace::TraceRawVcs, unit, TaskInput, TransientValue, TryJoinIterExt,
|
||||
Value, Vc,
|
||||
};
|
||||
use turbopack_binding::{
|
||||
turbo::{
|
||||
tasks_env::ProcessEnvVc,
|
||||
tasks_fs::{
|
||||
DiskFileSystemVc, FileSystem, FileSystemPathVc, FileSystemVc, VirtualFileSystemVc,
|
||||
},
|
||||
tasks_env::ProcessEnv,
|
||||
tasks_fs::{DiskFileSystem, FileSystem, FileSystemPath, VirtualFileSystem},
|
||||
},
|
||||
turbopack::{
|
||||
build::BuildChunkingContextVc,
|
||||
build::BuildChunkingContext,
|
||||
core::{
|
||||
chunk::{ChunkingContext, EvaluatableAssetsVc},
|
||||
compile_time_info::CompileTimeInfoVc,
|
||||
context::AssetContextVc,
|
||||
environment::ServerAddrVc,
|
||||
chunk::{ChunkingContext, EvaluatableAssets},
|
||||
compile_time_info::CompileTimeInfo,
|
||||
context::AssetContext,
|
||||
environment::ServerAddr,
|
||||
PROJECT_FILESYSTEM_NAME,
|
||||
},
|
||||
dev::DevChunkingContextVc,
|
||||
ecmascript::chunk::EcmascriptChunkingContextVc,
|
||||
dev::DevChunkingContext,
|
||||
ecmascript::chunk::EcmascriptChunkingContext,
|
||||
env::dotenv::load_env,
|
||||
node::execution_context::ExecutionContextVc,
|
||||
node::execution_context::ExecutionContext,
|
||||
turbopack::{
|
||||
evaluate_context::node_build_environment,
|
||||
module_options::ModuleOptionsContextVc,
|
||||
resolve_options_context::ResolveOptionsContextVc,
|
||||
transition::{ContextTransitionVc, TransitionsByNameVc},
|
||||
ModuleAssetContextVc,
|
||||
module_options::ModuleOptionsContext,
|
||||
resolve_options_context::ResolveOptionsContext,
|
||||
transition::{ContextTransition, TransitionsByName},
|
||||
ModuleAssetContext,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -58,7 +56,7 @@ use turbopack_binding::{
|
|||
use crate::{
|
||||
app::app_entry_point_to_route,
|
||||
pages::get_pages_routes,
|
||||
route::{EndpointVc, Route},
|
||||
route::{Endpoint, Route},
|
||||
};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, TaskInput)]
|
||||
|
@ -83,7 +81,7 @@ pub struct ProjectOptions {
|
|||
|
||||
#[derive(Serialize, Deserialize, TraceRawVcs, PartialEq, Eq, ValueDebugFormat)]
|
||||
pub struct Middleware {
|
||||
pub endpoint: EndpointVc,
|
||||
pub endpoint: Vc<Box<dyn Endpoint>>,
|
||||
pub config: NextSourceConfig,
|
||||
}
|
||||
|
||||
|
@ -106,7 +104,7 @@ pub struct Project {
|
|||
watch: bool,
|
||||
|
||||
/// Next config.
|
||||
next_config: NextConfigVc,
|
||||
next_config: Vc<NextConfig>,
|
||||
|
||||
browserslist_query: String,
|
||||
|
||||
|
@ -114,10 +112,10 @@ pub struct Project {
|
|||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ProjectVc {
|
||||
impl Project {
|
||||
#[turbo_tasks::function]
|
||||
pub async fn new(options: ProjectOptions) -> Result<Self> {
|
||||
let next_config = NextConfigVc::from_string(options.next_config);
|
||||
pub async fn new(options: ProjectOptions) -> Result<Vc<Self>> {
|
||||
let next_config = NextConfig::from_string(options.next_config);
|
||||
Ok(Project {
|
||||
root_path: options.root_path,
|
||||
project_path: options.project_path,
|
||||
|
@ -132,49 +130,49 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn project_fs(self) -> Result<FileSystemVc> {
|
||||
async fn project_fs(self: Vc<Self>) -> Result<Vc<Box<dyn FileSystem>>> {
|
||||
let this = self.await?;
|
||||
let disk_fs = DiskFileSystemVc::new(
|
||||
let disk_fs = DiskFileSystem::new(
|
||||
PROJECT_FILESYSTEM_NAME.to_string(),
|
||||
this.root_path.to_string(),
|
||||
);
|
||||
if this.watch {
|
||||
disk_fs.await?.start_watching_with_invalidation_reason()?;
|
||||
}
|
||||
Ok(disk_fs.into())
|
||||
Ok(Vc::upcast(disk_fs))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn client_fs(self) -> Result<FileSystemVc> {
|
||||
let virtual_fs = VirtualFileSystemVc::new();
|
||||
Ok(virtual_fs.into())
|
||||
async fn client_fs(self: Vc<Self>) -> Result<Vc<Box<dyn FileSystem>>> {
|
||||
let virtual_fs = VirtualFileSystem::new();
|
||||
Ok(Vc::upcast(virtual_fs))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn node_fs(self) -> Result<FileSystemVc> {
|
||||
async fn node_fs(self: Vc<Self>) -> Result<Vc<Box<dyn FileSystem>>> {
|
||||
let this = self.await?;
|
||||
let disk_fs = DiskFileSystemVc::new("node".to_string(), this.project_path.clone());
|
||||
let disk_fs = DiskFileSystem::new("node".to_string(), this.project_path.clone());
|
||||
disk_fs.await?.start_watching_with_invalidation_reason()?;
|
||||
Ok(disk_fs.into())
|
||||
Ok(Vc::upcast(disk_fs))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) fn node_root(self) -> FileSystemPathVc {
|
||||
self.node_fs().root().join(".next")
|
||||
pub(super) fn node_root(self: Vc<Self>) -> Vc<FileSystemPath> {
|
||||
self.node_fs().root().join(".next".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) fn client_root(self) -> FileSystemPathVc {
|
||||
pub(super) fn client_root(self: Vc<Self>) -> Vc<FileSystemPath> {
|
||||
self.client_fs().root()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn project_root_path(self) -> FileSystemPathVc {
|
||||
fn project_root_path(self: Vc<Self>) -> Vc<FileSystemPath> {
|
||||
self.project_fs().root()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn project_path(self) -> Result<FileSystemPathVc> {
|
||||
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();
|
||||
|
@ -182,13 +180,13 @@ impl ProjectVc {
|
|||
.strip_prefix(MAIN_SEPARATOR)
|
||||
.unwrap_or(project_relative)
|
||||
.replace(MAIN_SEPARATOR, "/");
|
||||
Ok(root.join(&project_relative))
|
||||
Ok(root.join(project_relative))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn pages_structure(self) -> Result<PagesStructureVc> {
|
||||
async fn pages_structure(self: Vc<Self>) -> Result<Vc<PagesStructure>> {
|
||||
let this: turbo_tasks::ReadRef<Project> = self.await?;
|
||||
let next_router_fs = VirtualFileSystemVc::new().as_file_system();
|
||||
let next_router_fs = Vc::upcast::<Box<dyn FileSystem>>(VirtualFileSystem::new());
|
||||
let next_router_root = next_router_fs.root();
|
||||
Ok(find_pages_structure(
|
||||
self.project_path(),
|
||||
|
@ -198,30 +196,31 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn env(self) -> ProcessEnvVc {
|
||||
fn env(self: Vc<Self>) -> Vc<Box<dyn ProcessEnv>> {
|
||||
load_env(self.project_path())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn next_config(self) -> Result<NextConfigVc> {
|
||||
async fn next_config(self: Vc<Self>) -> Result<Vc<NextConfig>> {
|
||||
Ok(self.await?.next_config)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn execution_context(self) -> ExecutionContextVc {
|
||||
fn execution_context(self: Vc<Self>) -> Vc<ExecutionContext> {
|
||||
let node_root = self.node_root();
|
||||
|
||||
let node_execution_chunking_context = DevChunkingContextVc::builder(
|
||||
self.project_path(),
|
||||
node_root,
|
||||
node_root.join("chunks"),
|
||||
node_root.join("assets"),
|
||||
node_build_environment(),
|
||||
)
|
||||
.build()
|
||||
.into();
|
||||
let node_execution_chunking_context = Vc::upcast(
|
||||
DevChunkingContext::builder(
|
||||
self.project_path(),
|
||||
node_root,
|
||||
node_root.join("chunks".to_string()),
|
||||
node_root.join("assets".to_string()),
|
||||
node_build_environment(),
|
||||
)
|
||||
.build(),
|
||||
);
|
||||
|
||||
ExecutionContextVc::new(
|
||||
ExecutionContext::new(
|
||||
self.project_path(),
|
||||
node_execution_chunking_context,
|
||||
self.env(),
|
||||
|
@ -229,40 +228,40 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn client_compile_time_info(self) -> Result<CompileTimeInfoVc> {
|
||||
async fn client_compile_time_info(self: Vc<Self>) -> Result<Vc<CompileTimeInfo>> {
|
||||
let this = self.await?;
|
||||
Ok(get_client_compile_time_info(
|
||||
this.mode,
|
||||
&this.browserslist_query,
|
||||
this.browserslist_query.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn server_compile_time_info(self) -> Result<CompileTimeInfoVc> {
|
||||
async fn server_compile_time_info(self: Vc<Self>) -> Result<Vc<CompileTimeInfo>> {
|
||||
let this = self.await?;
|
||||
Ok(get_server_compile_time_info(
|
||||
this.mode,
|
||||
self.env(),
|
||||
// TODO(alexkirsz) Fill this out.
|
||||
ServerAddrVc::empty(),
|
||||
ServerAddr::empty(),
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn pages_dir(self) -> Result<FileSystemPathVc> {
|
||||
async fn pages_dir(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
|
||||
Ok(if let Some(pages) = self.pages_structure().await?.pages {
|
||||
pages.project_path()
|
||||
} else {
|
||||
self.project_path().join("pages")
|
||||
self.project_path().join("pages".to_string())
|
||||
})
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn pages_transitions(self) -> TransitionsByNameVc {
|
||||
TransitionsByNameVc::cell(
|
||||
fn pages_transitions(self: Vc<Self>) -> Vc<TransitionsByName> {
|
||||
Vc::cell(
|
||||
[(
|
||||
"next-dynamic".to_string(),
|
||||
NextDynamicTransitionVc::new(self.pages_client_transition()).into(),
|
||||
Vc::upcast(NextDynamicTransition::new(self.pages_client_transition())),
|
||||
)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
|
@ -270,8 +269,8 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn pages_client_transition(self) -> ContextTransitionVc {
|
||||
ContextTransitionVc::new(
|
||||
fn pages_client_transition(self: Vc<Self>) -> Vc<ContextTransition> {
|
||||
ContextTransition::new(
|
||||
self.client_compile_time_info(),
|
||||
self.pages_client_module_options_context(),
|
||||
self.pages_client_resolve_options_context(),
|
||||
|
@ -279,7 +278,9 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn pages_client_module_options_context(self) -> Result<ModuleOptionsContextVc> {
|
||||
async fn pages_client_module_options_context(
|
||||
self: Vc<Self>,
|
||||
) -> Result<Vc<ModuleOptionsContext>> {
|
||||
let this = self.await?;
|
||||
Ok(get_client_module_options_context(
|
||||
self.project_path(),
|
||||
|
@ -294,7 +295,9 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn pages_client_resolve_options_context(self) -> Result<ResolveOptionsContextVc> {
|
||||
async fn pages_client_resolve_options_context(
|
||||
self: Vc<Self>,
|
||||
) -> Result<Vc<ResolveOptionsContext>> {
|
||||
let this = self.await?;
|
||||
Ok(get_client_resolve_options_context(
|
||||
self.project_path(),
|
||||
|
@ -308,40 +311,37 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) fn pages_client_module_context(self) -> AssetContextVc {
|
||||
ModuleAssetContextVc::new(
|
||||
pub(super) fn pages_client_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
||||
Vc::upcast(ModuleAssetContext::new(
|
||||
self.pages_transitions(),
|
||||
self.client_compile_time_info(),
|
||||
self.pages_client_module_options_context(),
|
||||
self.pages_client_resolve_options_context(),
|
||||
)
|
||||
.into()
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) fn pages_ssr_module_context(self) -> AssetContextVc {
|
||||
ModuleAssetContextVc::new(
|
||||
pub(super) fn pages_ssr_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
||||
Vc::upcast(ModuleAssetContext::new(
|
||||
self.pages_transitions(),
|
||||
self.server_compile_time_info(),
|
||||
self.pages_ssr_module_options_context(),
|
||||
self.pages_ssr_resolve_options_context(),
|
||||
)
|
||||
.into()
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) fn pages_ssr_data_module_context(self) -> AssetContextVc {
|
||||
ModuleAssetContextVc::new(
|
||||
pub(super) fn pages_ssr_data_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
||||
Vc::upcast(ModuleAssetContext::new(
|
||||
self.pages_transitions(),
|
||||
self.server_compile_time_info(),
|
||||
self.pages_ssr_data_module_options_context(),
|
||||
self.pages_ssr_resolve_options_context(),
|
||||
)
|
||||
.into()
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn pages_ssr_module_options_context(self) -> Result<ModuleOptionsContextVc> {
|
||||
async fn pages_ssr_module_options_context(self: Vc<Self>) -> Result<Vc<ModuleOptionsContext>> {
|
||||
let this = self.await?;
|
||||
Ok(get_server_module_options_context(
|
||||
self.project_path(),
|
||||
|
@ -355,7 +355,9 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn pages_ssr_data_module_options_context(self) -> Result<ModuleOptionsContextVc> {
|
||||
async fn pages_ssr_data_module_options_context(
|
||||
self: Vc<Self>,
|
||||
) -> Result<Vc<ModuleOptionsContext>> {
|
||||
let this = self.await?;
|
||||
Ok(get_server_module_options_context(
|
||||
self.project_path(),
|
||||
|
@ -369,7 +371,9 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn pages_ssr_resolve_options_context(self) -> Result<ResolveOptionsContextVc> {
|
||||
async fn pages_ssr_resolve_options_context(
|
||||
self: Vc<Self>,
|
||||
) -> Result<Vc<ResolveOptionsContext>> {
|
||||
let this = self.await?;
|
||||
Ok(get_server_resolve_options_context(
|
||||
self.project_path(),
|
||||
|
@ -383,7 +387,9 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn pages_client_runtime_entries(self) -> Result<EvaluatableAssetsVc> {
|
||||
pub(super) async fn pages_client_runtime_entries(
|
||||
self: Vc<Self>,
|
||||
) -> Result<Vc<EvaluatableAssets>> {
|
||||
let this = self.await?;
|
||||
let client_runtime_entries = get_client_runtime_entries(
|
||||
self.project_path(),
|
||||
|
@ -399,7 +405,7 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn pages_ssr_runtime_entries(self) -> Result<EvaluatableAssetsVc> {
|
||||
pub(super) async fn pages_ssr_runtime_entries(self: Vc<Self>) -> Result<Vc<EvaluatableAssets>> {
|
||||
let this = self.await?;
|
||||
let ssr_runtime_entries = get_server_runtime_entries(
|
||||
self.project_path(),
|
||||
|
@ -414,7 +420,9 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn client_chunking_context(self) -> Result<EcmascriptChunkingContextVc> {
|
||||
pub(super) async fn client_chunking_context(
|
||||
self: Vc<Self>,
|
||||
) -> Result<Vc<Box<dyn EcmascriptChunkingContext>>> {
|
||||
let this = self.await?;
|
||||
Ok(get_client_chunking_context(
|
||||
self.project_path(),
|
||||
|
@ -425,7 +433,7 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) fn server_chunking_context(self) -> BuildChunkingContextVc {
|
||||
pub(super) fn server_chunking_context(self: Vc<Self>) -> Vc<BuildChunkingContext> {
|
||||
get_server_chunking_context(
|
||||
self.project_path(),
|
||||
self.node_root(),
|
||||
|
@ -435,25 +443,29 @@ impl ProjectVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn ssr_chunking_context(self) -> Result<BuildChunkingContextVc> {
|
||||
let ssr_chunking_context = self.server_chunking_context().with_layer("ssr");
|
||||
BuildChunkingContextVc::resolve_from(ssr_chunking_context)
|
||||
pub(super) async fn ssr_chunking_context(self: Vc<Self>) -> Result<Vc<BuildChunkingContext>> {
|
||||
let ssr_chunking_context = self.server_chunking_context().with_layer("ssr".to_string());
|
||||
Vc::try_resolve_downcast_type::<BuildChunkingContext>(ssr_chunking_context)
|
||||
.await?
|
||||
.context("with_layer should not change the type of the chunking context")
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn ssr_data_chunking_context(self) -> Result<BuildChunkingContextVc> {
|
||||
let ssr_chunking_context = self.server_chunking_context().with_layer("ssr data");
|
||||
BuildChunkingContextVc::resolve_from(ssr_chunking_context)
|
||||
pub(super) async fn ssr_data_chunking_context(
|
||||
self: Vc<Self>,
|
||||
) -> Result<Vc<BuildChunkingContext>> {
|
||||
let ssr_chunking_context = self
|
||||
.server_chunking_context()
|
||||
.with_layer("ssr data".to_string());
|
||||
Vc::try_resolve_downcast_type::<BuildChunkingContext>(ssr_chunking_context)
|
||||
.await?
|
||||
.context("with_layer should not change the type of the chunking context")
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn rsc_chunking_context(self) -> Result<BuildChunkingContextVc> {
|
||||
let rsc_chunking_context = self.server_chunking_context().with_layer("rsc");
|
||||
BuildChunkingContextVc::resolve_from(rsc_chunking_context)
|
||||
pub(super) async fn rsc_chunking_context(self: Vc<Self>) -> Result<Vc<BuildChunkingContext>> {
|
||||
let rsc_chunking_context = self.server_chunking_context().with_layer("rsc".to_string());
|
||||
Vc::try_resolve_downcast_type::<BuildChunkingContext>(rsc_chunking_context)
|
||||
.await?
|
||||
.context("with_layer should not change the type of the chunking context")
|
||||
}
|
||||
|
@ -461,7 +473,7 @@ impl ProjectVc {
|
|||
/// Scans the app/pages directories for entry points files (matching the
|
||||
/// provided page_extensions).
|
||||
#[turbo_tasks::function]
|
||||
pub async fn entrypoints(self) -> Result<EntrypointsVc> {
|
||||
pub async fn entrypoints(self: Vc<Self>) -> Result<Vc<Entrypoints>> {
|
||||
let this = self.await?;
|
||||
let mut routes = IndexMap::new();
|
||||
if let Some(app_dir) = *find_app_dir(self.project_path()).await? {
|
||||
|
@ -501,17 +513,16 @@ impl ProjectVc {
|
|||
/// Emits opaque HMR events whenever a change is detected in the chunk group
|
||||
/// internally known as `identifier`.
|
||||
#[turbo_tasks::function]
|
||||
pub fn hmr_events(self, _identifier: String, _sender: TransientValue<()>) -> NothingVc {
|
||||
NothingVc::new()
|
||||
pub fn hmr_events(self: Vc<Self>, _identifier: String, _sender: TransientValue<()>) -> Vc<()> {
|
||||
unit()
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn project_fs(project_dir: &str, watching: bool) -> Result<FileSystemVc> {
|
||||
let disk_fs =
|
||||
DiskFileSystemVc::new(PROJECT_FILESYSTEM_NAME.to_string(), project_dir.to_string());
|
||||
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());
|
||||
if watching {
|
||||
disk_fs.await?.start_watching_with_invalidation_reason()?;
|
||||
}
|
||||
Ok(disk_fs.into())
|
||||
Ok(Vc::upcast(disk_fs))
|
||||
}
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
use anyhow::Result;
|
||||
use indexmap::IndexMap;
|
||||
use turbo_tasks::CompletionVc;
|
||||
use turbo_tasks::{Completion, Vc};
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Route {
|
||||
Page {
|
||||
html_endpoint: EndpointVc,
|
||||
data_endpoint: EndpointVc,
|
||||
html_endpoint: Vc<Box<dyn Endpoint>>,
|
||||
data_endpoint: Vc<Box<dyn Endpoint>>,
|
||||
},
|
||||
PageApi {
|
||||
endpoint: EndpointVc,
|
||||
endpoint: Vc<Box<dyn Endpoint>>,
|
||||
},
|
||||
AppPage {
|
||||
html_endpoint: EndpointVc,
|
||||
rsc_endpoint: EndpointVc,
|
||||
html_endpoint: Vc<Box<dyn Endpoint>>,
|
||||
rsc_endpoint: Vc<Box<dyn Endpoint>>,
|
||||
},
|
||||
AppRoute {
|
||||
endpoint: EndpointVc,
|
||||
endpoint: Vc<Box<dyn Endpoint>>,
|
||||
},
|
||||
Conflict,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_trait]
|
||||
pub trait Endpoint {
|
||||
fn write_to_disk(&self) -> WrittenEndpointVc;
|
||||
fn changed(&self) -> CompletionVc;
|
||||
fn write_to_disk(self: Vc<Self>) -> Vc<WrittenEndpoint>;
|
||||
fn changed(self: Vc<Self>) -> Vc<Completion>;
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(async_fn_in_trait)]
|
||||
|
||||
use turbopack_binding::turbo::{
|
||||
tasks::{run_once, TransientInstance, TurboTasks},
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
#![feature(arbitrary_self_types)]
|
||||
#![feature(async_fn_in_trait)]
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Result;
|
||||
|
|
|
@ -2,15 +2,18 @@ use std::collections::HashSet;
|
|||
|
||||
use anyhow::Result;
|
||||
use indexmap::IndexMap;
|
||||
use next_core::{self, next_client_reference::ClientReferenceType};
|
||||
use turbo_tasks::TryJoinIterExt;
|
||||
use next_core::{
|
||||
next_client_reference::ClientReferenceType,
|
||||
{self},
|
||||
};
|
||||
use turbo_tasks::{TryJoinIterExt, Vc};
|
||||
use turbopack_binding::turbopack::{
|
||||
build::BuildChunkingContextVc,
|
||||
build::BuildChunkingContext,
|
||||
core::{
|
||||
chunk::{ChunkableModule, ChunkingContext},
|
||||
output::{OutputAssetVc, OutputAssetsVc},
|
||||
output::{OutputAsset, OutputAssets},
|
||||
},
|
||||
ecmascript::chunk::EcmascriptChunkingContextVc,
|
||||
ecmascript::chunk::EcmascriptChunkingContext,
|
||||
};
|
||||
|
||||
/// Computes all client references chunks, and adds them to the relevant
|
||||
|
@ -20,9 +23,9 @@ use turbopack_binding::turbopack::{
|
|||
/// type needs to load.
|
||||
pub async fn compute_app_client_references_chunks(
|
||||
app_client_reference_types: &HashSet<ClientReferenceType>,
|
||||
client_chunking_context: EcmascriptChunkingContextVc,
|
||||
ssr_chunking_context: BuildChunkingContextVc,
|
||||
all_chunks: &mut Vec<OutputAssetVc>,
|
||||
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
ssr_chunking_context: Vc<BuildChunkingContext>,
|
||||
all_chunks: &mut Vec<Vc<Box<dyn OutputAsset>>>,
|
||||
) -> Result<IndexMap<ClientReferenceType, ClientReferenceChunks>> {
|
||||
let app_client_references_chunks: IndexMap<_, _> = app_client_reference_types
|
||||
.iter()
|
||||
|
@ -34,10 +37,10 @@ pub async fn compute_app_client_references_chunks(
|
|||
let ecmascript_client_reference_ref = ecmascript_client_reference.await?;
|
||||
let client_entry_chunk = ecmascript_client_reference_ref
|
||||
.client_module
|
||||
.as_root_chunk(client_chunking_context.into());
|
||||
.as_root_chunk(Vc::upcast(client_chunking_context));
|
||||
let ssr_entry_chunk = ecmascript_client_reference_ref
|
||||
.ssr_module
|
||||
.as_root_chunk(ssr_chunking_context.into());
|
||||
.as_root_chunk(Vc::upcast(ssr_chunking_context));
|
||||
ClientReferenceChunks {
|
||||
client_chunks: client_chunking_context.chunk_group(client_entry_chunk),
|
||||
ssr_chunks: ssr_chunking_context.chunk_group(ssr_entry_chunk),
|
||||
|
@ -47,10 +50,10 @@ pub async fn compute_app_client_references_chunks(
|
|||
let css_client_reference_ref = css_client_reference.await?;
|
||||
let client_entry_chunk = css_client_reference_ref
|
||||
.client_module
|
||||
.as_root_chunk(client_chunking_context.into());
|
||||
.as_root_chunk(Vc::upcast(client_chunking_context));
|
||||
ClientReferenceChunks {
|
||||
client_chunks: client_chunking_context.chunk_group(client_entry_chunk),
|
||||
ssr_chunks: OutputAssetsVc::empty(),
|
||||
ssr_chunks: OutputAssets::empty(),
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -82,7 +85,7 @@ pub async fn compute_app_client_references_chunks(
|
|||
/// Contains the chunks corresponding to a client reference.
|
||||
pub struct ClientReferenceChunks {
|
||||
/// Chunks to be loaded on the client.
|
||||
pub client_chunks: OutputAssetsVc,
|
||||
pub client_chunks: Vc<OutputAssets>,
|
||||
/// Chunks to be loaded on the server for SSR.
|
||||
pub ssr_chunks: OutputAssetsVc,
|
||||
pub ssr_chunks: Vc<OutputAssets>,
|
||||
}
|
||||
|
|
|
@ -11,47 +11,44 @@ use next_core::{
|
|||
get_client_runtime_entries, ClientContextType,
|
||||
},
|
||||
next_client_reference::{
|
||||
ClientReference, ClientReferenceType, NextEcmascriptClientReferenceTransitionVc,
|
||||
ClientReference, ClientReferenceType, NextEcmascriptClientReferenceTransition,
|
||||
},
|
||||
next_config::NextConfigVc,
|
||||
next_dynamic::NextDynamicTransitionVc,
|
||||
next_config::NextConfig,
|
||||
next_dynamic::NextDynamicTransition,
|
||||
next_server::{
|
||||
get_server_module_options_context, get_server_resolve_options_context,
|
||||
get_server_runtime_entries, ServerContextType,
|
||||
},
|
||||
};
|
||||
use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value, ValueToString};
|
||||
use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::{
|
||||
tasks_env::{CustomProcessEnvVc, ProcessEnvVc},
|
||||
tasks_fs::{File, FileSystemPath, FileSystemPathVc},
|
||||
tasks_env::{CustomProcessEnv, ProcessEnv},
|
||||
tasks_fs::{File, FileSystemPath},
|
||||
},
|
||||
turbopack::{
|
||||
build::BuildChunkingContextVc,
|
||||
build::BuildChunkingContext,
|
||||
core::{
|
||||
asset::{Asset, AssetVc},
|
||||
asset::{Asset, AssetContent},
|
||||
chunk::{
|
||||
availability_info::AvailabilityInfo, ChunkingContext, EvaluatableAssetsVc,
|
||||
availability_info::AvailabilityInfo, ChunkingContext, EvaluatableAssets,
|
||||
ModuleId as TurbopackModuleId,
|
||||
},
|
||||
compile_time_info::CompileTimeInfoVc,
|
||||
file_source::FileSourceVc,
|
||||
output::{OutputAssetVc, OutputAssetsVc},
|
||||
raw_output::RawOutputVc,
|
||||
virtual_source::VirtualSourceVc,
|
||||
compile_time_info::CompileTimeInfo,
|
||||
file_source::FileSource,
|
||||
output::{OutputAsset, OutputAssets},
|
||||
raw_output::RawOutput,
|
||||
virtual_source::VirtualSource,
|
||||
},
|
||||
ecmascript::{
|
||||
chunk::{
|
||||
EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkPlaceablesVc,
|
||||
EcmascriptChunkVc, EcmascriptChunkingContextVc,
|
||||
EcmascriptChunk, EcmascriptChunkItemExt, EcmascriptChunkPlaceable,
|
||||
EcmascriptChunkingContext,
|
||||
},
|
||||
utils::StringifyJs,
|
||||
},
|
||||
node::execution_context::ExecutionContextVc,
|
||||
turbopack::{
|
||||
transition::{ContextTransitionVc, TransitionsByNameVc},
|
||||
ModuleAssetContextVc,
|
||||
},
|
||||
node::execution_context::ExecutionContext,
|
||||
turbopack::{transition::ContextTransition, ModuleAssetContext},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -73,38 +70,38 @@ pub struct AppEntry {
|
|||
/// the pathname to refer to this entry.
|
||||
pub original_name: String,
|
||||
/// The RSC module asset for the route or page.
|
||||
pub rsc_entry: EcmascriptChunkPlaceableVc,
|
||||
pub rsc_entry: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value]
|
||||
pub struct AppEntries {
|
||||
/// All app entries.
|
||||
pub entries: Vec<AppEntryVc>,
|
||||
pub entries: Vec<Vc<AppEntry>>,
|
||||
/// The RSC runtime entries that should be evaluated before any app entry
|
||||
/// module when server rendering.
|
||||
pub rsc_runtime_entries: EvaluatableAssetsVc,
|
||||
pub rsc_runtime_entries: Vc<EvaluatableAssets>,
|
||||
/// The client runtime entries that should be evaluated before any app entry
|
||||
/// module when client rendering.
|
||||
pub client_runtime_entries: EvaluatableAssetsVc,
|
||||
pub client_runtime_entries: Vc<EvaluatableAssets>,
|
||||
}
|
||||
|
||||
/// Computes all app entries found under the given project root.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_app_entries(
|
||||
project_root: FileSystemPathVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
env: ProcessEnvVc,
|
||||
client_compile_time_info: CompileTimeInfoVc,
|
||||
server_compile_time_info: CompileTimeInfoVc,
|
||||
next_config: NextConfigVc,
|
||||
) -> Result<AppEntriesVc> {
|
||||
project_root: Vc<FileSystemPath>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
env: Vc<Box<dyn ProcessEnv>>,
|
||||
client_compile_time_info: Vc<CompileTimeInfo>,
|
||||
server_compile_time_info: Vc<CompileTimeInfo>,
|
||||
next_config: Vc<NextConfig>,
|
||||
) -> Result<Vc<AppEntries>> {
|
||||
let app_dir = find_app_dir_if_enabled(project_root, next_config);
|
||||
|
||||
let Some(&app_dir) = app_dir.await?.as_ref() else {
|
||||
return Ok(AppEntriesVc::cell(AppEntries {
|
||||
return Ok(AppEntries::cell(AppEntries {
|
||||
entries: vec![],
|
||||
rsc_runtime_entries: EvaluatableAssetsVc::empty(),
|
||||
client_runtime_entries: EvaluatableAssetsVc::empty(),
|
||||
rsc_runtime_entries: EvaluatableAssets::empty(),
|
||||
client_runtime_entries: EvaluatableAssets::empty(),
|
||||
}));
|
||||
};
|
||||
|
||||
|
@ -124,7 +121,7 @@ pub async fn get_app_entries(
|
|||
// app_source?
|
||||
let runtime_entries = get_server_runtime_entries(project_root, env, rsc_ty, mode, next_config);
|
||||
|
||||
let env = CustomProcessEnvVc::new(env, next_config.env()).as_process_env();
|
||||
let env = Vc::upcast(CustomProcessEnv::new(env, next_config.env()));
|
||||
|
||||
let ssr_ty: Value<ServerContextType> = Value::new(ServerContextType::AppSSR { app_dir });
|
||||
|
||||
|
@ -147,7 +144,7 @@ pub async fn get_app_entries(
|
|||
execution_context,
|
||||
);
|
||||
|
||||
let client_transition = ContextTransitionVc::new(
|
||||
let client_transition = ContextTransition::new(
|
||||
client_compile_time_info,
|
||||
client_module_options_context,
|
||||
client_resolve_options_context,
|
||||
|
@ -169,7 +166,7 @@ pub async fn get_app_entries(
|
|||
next_config,
|
||||
);
|
||||
|
||||
let ssr_transition = ContextTransitionVc::new(
|
||||
let ssr_transition = ContextTransition::new(
|
||||
server_compile_time_info,
|
||||
ssr_module_options_context,
|
||||
ssr_resolve_options_context,
|
||||
|
@ -179,19 +176,22 @@ pub async fn get_app_entries(
|
|||
|
||||
transitions.insert(
|
||||
ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string(),
|
||||
NextEcmascriptClientReferenceTransitionVc::new(client_transition, ssr_transition).into(),
|
||||
Vc::upcast(NextEcmascriptClientReferenceTransition::new(
|
||||
client_transition,
|
||||
ssr_transition,
|
||||
)),
|
||||
);
|
||||
|
||||
let client_ty = Value::new(ClientContextType::App { app_dir });
|
||||
transitions.insert(
|
||||
"next-dynamic".to_string(),
|
||||
NextDynamicTransitionVc::new(client_transition).into(),
|
||||
Vc::upcast(NextDynamicTransition::new(client_transition)),
|
||||
);
|
||||
|
||||
let rsc_ty = Value::new(ServerContextType::AppRSC {
|
||||
app_dir,
|
||||
client_transition: Some(client_transition.into()),
|
||||
ecmascript_client_reference_transition_name: Some(StringVc::cell(
|
||||
client_transition: Some(Vc::upcast(client_transition)),
|
||||
ecmascript_client_reference_transition_name: Some(Vc::cell(
|
||||
ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string(),
|
||||
)),
|
||||
});
|
||||
|
@ -211,8 +211,8 @@ pub async fn get_app_entries(
|
|||
execution_context,
|
||||
);
|
||||
|
||||
let rsc_context = ModuleAssetContextVc::new(
|
||||
TransitionsByNameVc::cell(transitions),
|
||||
let rsc_context = ModuleAssetContext::new(
|
||||
Vc::cell(transitions),
|
||||
server_compile_time_info,
|
||||
rsc_module_options_context,
|
||||
rsc_resolve_options_context,
|
||||
|
@ -230,7 +230,7 @@ pub async fn get_app_entries(
|
|||
Entrypoint::AppRoute { path } => {
|
||||
get_app_route_entry(
|
||||
rsc_context,
|
||||
FileSourceVc::new(*path).into(),
|
||||
Vc::upcast(FileSource::new(*path)),
|
||||
pathname,
|
||||
project_root,
|
||||
)
|
||||
|
@ -248,8 +248,8 @@ pub async fn get_app_entries(
|
|||
entries.push(get_app_route_favicon_entry(rsc_context, favicon, project_root).await?);
|
||||
}
|
||||
|
||||
let client_context = ModuleAssetContextVc::new(
|
||||
TransitionsByNameVc::cell(Default::default()),
|
||||
let client_context = ModuleAssetContext::new(
|
||||
Vc::cell(Default::default()),
|
||||
client_compile_time_info,
|
||||
client_module_options_context,
|
||||
client_resolve_options_context,
|
||||
|
@ -264,10 +264,10 @@ pub async fn get_app_entries(
|
|||
execution_context,
|
||||
);
|
||||
|
||||
Ok(AppEntriesVc::cell(AppEntries {
|
||||
Ok(AppEntries::cell(AppEntries {
|
||||
entries,
|
||||
rsc_runtime_entries: runtime_entries.resolve_entries(rsc_context.into()),
|
||||
client_runtime_entries: client_runtime_entries.resolve_entries(client_context.into()),
|
||||
rsc_runtime_entries: runtime_entries.resolve_entries(Vc::upcast(rsc_context)),
|
||||
client_runtime_entries: client_runtime_entries.resolve_entries(Vc::upcast(client_context)),
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -276,18 +276,18 @@ pub async fn get_app_entries(
|
|||
/// manifests.
|
||||
pub async fn compute_app_entries_chunks(
|
||||
app_entries: &AppEntries,
|
||||
app_client_references_by_entry: &IndexMap<AssetVc, Vec<ClientReference>>,
|
||||
app_client_references_by_entry: &IndexMap<Vc<Box<dyn Asset>>, Vec<ClientReference>>,
|
||||
app_client_references_chunks: &IndexMap<ClientReferenceType, ClientReferenceChunks>,
|
||||
rsc_chunking_context: BuildChunkingContextVc,
|
||||
client_chunking_context: EcmascriptChunkingContextVc,
|
||||
ssr_chunking_context: EcmascriptChunkingContextVc,
|
||||
node_root: FileSystemPathVc,
|
||||
rsc_chunking_context: Vc<BuildChunkingContext>,
|
||||
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
ssr_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
node_root: Vc<FileSystemPath>,
|
||||
client_relative_path: &FileSystemPath,
|
||||
app_paths_manifest_dir_path: &FileSystemPath,
|
||||
app_build_manifest: &mut AppBuildManifest,
|
||||
build_manifest: &mut BuildManifest,
|
||||
app_paths_manifest: &mut AppPathsManifest,
|
||||
all_chunks: &mut Vec<OutputAssetVc>,
|
||||
all_chunks: &mut Vec<Vc<Box<dyn OutputAsset>>>,
|
||||
) -> Result<()> {
|
||||
let node_root_ref = node_root.await?;
|
||||
|
||||
|
@ -299,7 +299,7 @@ pub async fn compute_app_entries_chunks(
|
|||
all_chunks.push(chunk);
|
||||
|
||||
let chunk_path = chunk.ident().path().await?;
|
||||
if chunk_path.extension() == Some("js") {
|
||||
if chunk_path.extension_ref() == Some("js") {
|
||||
if let Some(chunk_path) = client_relative_path.get_path_to(&chunk_path) {
|
||||
app_shared_client_chunks_paths.push(chunk_path.to_string());
|
||||
build_manifest.root_main_files.push(chunk_path.to_string());
|
||||
|
@ -311,11 +311,11 @@ pub async fn compute_app_entries_chunks(
|
|||
let app_entry = app_entry.await?;
|
||||
|
||||
let app_entry_client_references = app_client_references_by_entry
|
||||
.get(&app_entry.rsc_entry.as_asset())
|
||||
.get(&Vc::upcast(app_entry.rsc_entry))
|
||||
.expect("app entry should have a corresponding client references list");
|
||||
|
||||
let rsc_chunk = rsc_chunking_context.entry_chunk(
|
||||
node_root.join(&format!(
|
||||
node_root.join(format!(
|
||||
"server/app/{original_name}.js",
|
||||
original_name = app_entry.original_name
|
||||
)),
|
||||
|
@ -388,7 +388,7 @@ pub async fn compute_app_entries_chunks(
|
|||
if let Some(server_component) = app_client_reference.server_component() {
|
||||
let server_component_name = server_component
|
||||
.server_path()
|
||||
.with_extension("")
|
||||
.with_extension("".to_string())
|
||||
.to_string()
|
||||
.await?;
|
||||
|
||||
|
@ -414,7 +414,7 @@ pub async fn compute_app_entries_chunks(
|
|||
client_chunks_paths
|
||||
.iter()
|
||||
.filter_map(|chunk_path| {
|
||||
if chunk_path.extension() == Some("css") {
|
||||
if chunk_path.extension_ref() == Some("css") {
|
||||
client_relative_path.get_path_to(chunk_path)
|
||||
} else {
|
||||
None
|
||||
|
@ -506,22 +506,26 @@ pub async fn compute_app_entries_chunks(
|
|||
}
|
||||
|
||||
let client_reference_manifest_json = serde_json::to_string(&entry_manifest).unwrap();
|
||||
let client_reference_manifest_source = VirtualSourceVc::new(
|
||||
node_root.join(&format!(
|
||||
let client_reference_manifest_source = VirtualSource::new(
|
||||
node_root.join(format!(
|
||||
"server/app/{original_name}_client-reference-manifest.js",
|
||||
original_name = app_entry.original_name
|
||||
)),
|
||||
File::from(formatdoc! {
|
||||
r#"
|
||||
AssetContent::file(
|
||||
File::from(formatdoc! {
|
||||
r#"
|
||||
globalThis.__RSC_MANIFEST = globalThis.__RSC_MANIFEST || {{}};
|
||||
globalThis.__RSC_MANIFEST[{original_name}] = {manifest}
|
||||
"#,
|
||||
original_name = StringifyJs(&app_entry.original_name),
|
||||
manifest = StringifyJs(&client_reference_manifest_json)
|
||||
})
|
||||
.into(),
|
||||
original_name = StringifyJs(&app_entry.original_name),
|
||||
manifest = StringifyJs(&client_reference_manifest_json)
|
||||
})
|
||||
.into(),
|
||||
),
|
||||
);
|
||||
all_chunks.push(RawOutputVc::new(client_reference_manifest_source.into()).into());
|
||||
all_chunks.push(Vc::upcast(RawOutput::new(Vc::upcast(
|
||||
client_reference_manifest_source,
|
||||
))));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -529,23 +533,25 @@ pub async fn compute_app_entries_chunks(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_app_shared_client_chunk(
|
||||
app_client_runtime_entries: EvaluatableAssetsVc,
|
||||
client_chunking_context: EcmascriptChunkingContextVc,
|
||||
) -> Result<EcmascriptChunkVc> {
|
||||
app_client_runtime_entries: Vc<EvaluatableAssets>,
|
||||
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
) -> Result<Vc<EcmascriptChunk>> {
|
||||
let client_runtime_entries: Vec<_> = app_client_runtime_entries
|
||||
.await?
|
||||
.iter()
|
||||
.map(|entry| async move { Ok(EcmascriptChunkPlaceableVc::resolve_from(*entry).await?) })
|
||||
.map(|entry| async move {
|
||||
Ok(Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(*entry).await?)
|
||||
})
|
||||
.try_join()
|
||||
.await?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
Ok(EcmascriptChunkVc::new_normalized(
|
||||
Ok(EcmascriptChunk::new_normalized(
|
||||
client_chunking_context,
|
||||
// TODO(alexkirsz) Should this accept Evaluatable instead?
|
||||
EcmascriptChunkPlaceablesVc::cell(client_runtime_entries),
|
||||
Vc::cell(client_runtime_entries),
|
||||
None,
|
||||
Value::new(AvailabilityInfo::Untracked),
|
||||
))
|
||||
|
@ -553,18 +559,20 @@ pub async fn get_app_shared_client_chunk(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_app_client_shared_chunks(
|
||||
app_client_runtime_entries: EvaluatableAssetsVc,
|
||||
client_chunking_context: EcmascriptChunkingContextVc,
|
||||
) -> Result<OutputAssetsVc> {
|
||||
app_client_runtime_entries: Vc<EvaluatableAssets>,
|
||||
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
) -> Result<Vc<OutputAssets>> {
|
||||
if app_client_runtime_entries.await?.is_empty() {
|
||||
return Ok(OutputAssetsVc::empty());
|
||||
return Ok(OutputAssets::empty());
|
||||
}
|
||||
|
||||
let app_client_shared_chunk =
|
||||
get_app_shared_client_chunk(app_client_runtime_entries, client_chunking_context);
|
||||
|
||||
let app_client_shared_chunks = client_chunking_context
|
||||
.evaluated_chunk_group(app_client_shared_chunk.into(), app_client_runtime_entries);
|
||||
let app_client_shared_chunks = client_chunking_context.evaluated_chunk_group(
|
||||
Vc::upcast(app_client_shared_chunk),
|
||||
app_client_runtime_entries,
|
||||
);
|
||||
|
||||
Ok(app_client_shared_chunks)
|
||||
}
|
||||
|
|
|
@ -3,37 +3,36 @@ use std::io::Write;
|
|||
use anyhow::{bail, Result};
|
||||
use indoc::writedoc;
|
||||
use next_core::{
|
||||
app_structure::LoaderTreeVc,
|
||||
app_structure::LoaderTree,
|
||||
loader_tree::{LoaderTreeModule, ServerComponentTransition},
|
||||
mode::NextMode,
|
||||
next_server_component::NextServerComponentTransitionVc,
|
||||
next_server_component::NextServerComponentTransition,
|
||||
UnsupportedDynamicMetadataIssue,
|
||||
};
|
||||
use turbo_tasks::{TryJoinIterExt, Value, ValueToString};
|
||||
use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPathVc},
|
||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPath},
|
||||
turbopack::{
|
||||
core::{
|
||||
context::AssetContext,
|
||||
reference_type::{InnerAssetsVc, ReferenceType},
|
||||
virtual_source::VirtualSourceVc,
|
||||
asset::AssetContent, context::AssetContext, issue::IssueExt,
|
||||
reference_type::ReferenceType, virtual_source::VirtualSource,
|
||||
},
|
||||
ecmascript::{chunk::EcmascriptChunkPlaceableVc, utils::StringifyJs},
|
||||
turbopack::ModuleAssetContextVc,
|
||||
ecmascript::{chunk::EcmascriptChunkPlaceable, utils::StringifyJs},
|
||||
turbopack::ModuleAssetContext,
|
||||
},
|
||||
};
|
||||
|
||||
use super::app_entries::{AppEntry, AppEntryVc};
|
||||
use super::app_entries::AppEntry;
|
||||
|
||||
/// Computes the entry for a Next.js app page.
|
||||
pub(super) async fn get_app_page_entry(
|
||||
context: ModuleAssetContextVc,
|
||||
loader_tree: LoaderTreeVc,
|
||||
app_dir: FileSystemPathVc,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
loader_tree: Vc<LoaderTree>,
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
pathname: &str,
|
||||
project_root: FileSystemPathVc,
|
||||
) -> Result<AppEntryVc> {
|
||||
let server_component_transition = NextServerComponentTransitionVc::new().into();
|
||||
project_root: Vc<FileSystemPath>,
|
||||
) -> Result<Vc<AppEntry>> {
|
||||
let server_component_transition = Vc::upcast(NextServerComponentTransition::new());
|
||||
|
||||
let loader_tree = LoaderTreeModule::build(
|
||||
loader_tree,
|
||||
|
@ -57,7 +56,6 @@ pub(super) async fn get_app_page_entry(
|
|||
files: unsupported_metadata,
|
||||
}
|
||||
.cell()
|
||||
.as_issue()
|
||||
.emit();
|
||||
}
|
||||
|
||||
|
@ -95,14 +93,16 @@ pub(super) async fn get_app_page_entry(
|
|||
let file = File::from(result.build());
|
||||
let source =
|
||||
// TODO(alexkirsz) Figure out how to name this virtual asset.
|
||||
VirtualSourceVc::new(project_root.join("todo.tsx"), file.into());
|
||||
VirtualSource::new(project_root.join("todo.tsx".to_string()), AssetContent::file(file.into()));
|
||||
|
||||
let rsc_entry = context.process(
|
||||
source.into(),
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(inner_assets))),
|
||||
Vc::upcast(source),
|
||||
Value::new(ReferenceType::Internal(Vc::cell(inner_assets))),
|
||||
);
|
||||
|
||||
let Some(rsc_entry) = EcmascriptChunkPlaceableVc::resolve_from(rsc_entry).await? else {
|
||||
let Some(rsc_entry) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(rsc_entry).await?
|
||||
else {
|
||||
bail!("expected an ECMAScript chunk placeable asset");
|
||||
};
|
||||
|
||||
|
|
|
@ -4,31 +4,31 @@ use anyhow::{bail, Result};
|
|||
use indexmap::indexmap;
|
||||
use indoc::writedoc;
|
||||
use serde::Serialize;
|
||||
use turbo_tasks::{Value, ValueToString};
|
||||
use turbo_tasks::{Value, ValueToString, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPathVc},
|
||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPath},
|
||||
turbopack::{
|
||||
core::{
|
||||
asset::Asset,
|
||||
asset::{Asset, AssetContent},
|
||||
context::AssetContext,
|
||||
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssetsVc, ReferenceType},
|
||||
source::SourceVc,
|
||||
virtual_source::VirtualSourceVc,
|
||||
reference_type::{EcmaScriptModulesReferenceSubType, ReferenceType},
|
||||
source::Source,
|
||||
virtual_source::VirtualSource,
|
||||
},
|
||||
ecmascript::{chunk::EcmascriptChunkPlaceableVc, utils::StringifyJs},
|
||||
turbopack::ModuleAssetContextVc,
|
||||
ecmascript::{chunk::EcmascriptChunkPlaceable, utils::StringifyJs},
|
||||
turbopack::ModuleAssetContext,
|
||||
},
|
||||
};
|
||||
|
||||
use super::app_entries::{AppEntry, AppEntryVc};
|
||||
use super::app_entries::AppEntry;
|
||||
|
||||
/// Computes the entry for a Next.js app route.
|
||||
pub(super) async fn get_app_route_entry(
|
||||
rsc_context: ModuleAssetContextVc,
|
||||
source: SourceVc,
|
||||
rsc_context: Vc<ModuleAssetContext>,
|
||||
source: Vc<Box<dyn Source>>,
|
||||
pathname: &str,
|
||||
project_root: FileSystemPathVc,
|
||||
) -> Result<AppEntryVc> {
|
||||
project_root: Vc<FileSystemPath>,
|
||||
) -> Result<Vc<AppEntry>> {
|
||||
let mut result = RopeBuilder::default();
|
||||
|
||||
let kind = "app-route";
|
||||
|
@ -99,7 +99,10 @@ pub(super) async fn get_app_route_entry(
|
|||
|
||||
let file = File::from(result.build());
|
||||
// TODO(alexkirsz) Figure out how to name this virtual asset.
|
||||
let virtual_source = VirtualSourceVc::new(project_root.join("todo.tsx"), file.into());
|
||||
let virtual_source = VirtualSource::new(
|
||||
project_root.join("todo.tsx".to_string()),
|
||||
AssetContent::file(file.into()),
|
||||
);
|
||||
|
||||
let entry = rsc_context.process(
|
||||
source,
|
||||
|
@ -109,15 +112,17 @@ pub(super) async fn get_app_route_entry(
|
|||
);
|
||||
|
||||
let inner_assets = indexmap! {
|
||||
"ENTRY".to_string() => entry.into()
|
||||
"ENTRY".to_string() => Vc::upcast(entry)
|
||||
};
|
||||
|
||||
let rsc_entry = rsc_context.process(
|
||||
virtual_source.into(),
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(inner_assets))),
|
||||
Vc::upcast(virtual_source),
|
||||
Value::new(ReferenceType::Internal(Vc::cell(inner_assets))),
|
||||
);
|
||||
|
||||
let Some(rsc_entry) = EcmascriptChunkPlaceableVc::resolve_from(rsc_entry).await? else {
|
||||
let Some(rsc_entry) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(rsc_entry).await?
|
||||
else {
|
||||
bail!("expected an ECMAScript chunk placeable asset");
|
||||
};
|
||||
|
||||
|
|
|
@ -4,23 +4,24 @@ use anyhow::{bail, Result};
|
|||
use base64::{display::Base64Display, engine::general_purpose::STANDARD};
|
||||
use indoc::writedoc;
|
||||
use next_core::app_structure::MetadataItem;
|
||||
use turbo_tasks::ValueToString;
|
||||
use turbo_tasks::{ValueToString, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileContent, FileSystemPathVc},
|
||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileContent, FileSystemPath},
|
||||
turbopack::{
|
||||
core::virtual_source::VirtualSourceVc, ecmascript::utils::StringifyJs,
|
||||
turbopack::ModuleAssetContextVc,
|
||||
core::{asset::AssetContent, virtual_source::VirtualSource},
|
||||
ecmascript::utils::StringifyJs,
|
||||
turbopack::ModuleAssetContext,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{app_entries::AppEntryVc, app_route_entry::get_app_route_entry};
|
||||
use super::{app_entries::AppEntry, app_route_entry::get_app_route_entry};
|
||||
|
||||
/// Computes the entry for a Next.js favicon file.
|
||||
pub(super) async fn get_app_route_favicon_entry(
|
||||
rsc_context: ModuleAssetContextVc,
|
||||
rsc_context: Vc<ModuleAssetContext>,
|
||||
favicon: MetadataItem,
|
||||
project_root: FileSystemPathVc,
|
||||
) -> Result<AppEntryVc> {
|
||||
project_root: Vc<FileSystemPath>,
|
||||
) -> Result<Vc<AppEntry>> {
|
||||
let path = match favicon {
|
||||
// TODO(alexkirsz) Is there a difference here?
|
||||
MetadataItem::Static { path } => path,
|
||||
|
@ -74,11 +75,11 @@ pub(super) async fn get_app_route_favicon_entry(
|
|||
let file = File::from(code.build());
|
||||
let source =
|
||||
// TODO(alexkirsz) Figure out how to name this virtual source.
|
||||
VirtualSourceVc::new(project_root.join("todo.tsx"), file.into());
|
||||
VirtualSource::new(project_root.join("todo.tsx".to_string()), AssetContent::file(file.into()));
|
||||
|
||||
get_app_route_entry(
|
||||
rsc_context,
|
||||
source.into(),
|
||||
Vc::upcast(source),
|
||||
// TODO(alexkirsz) Get this from the metadata?
|
||||
"/favicon.ico",
|
||||
project_root,
|
||||
|
|
|
@ -7,42 +7,38 @@ use std::{
|
|||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use dunce::canonicalize;
|
||||
use next_core::{
|
||||
self,
|
||||
mode::NextMode,
|
||||
next_client::{get_client_chunking_context, get_client_compile_time_info},
|
||||
next_client_reference::{ClientReferenceType, ClientReferencesByEntryVc},
|
||||
next_client_reference::{ClientReferenceType, ClientReferencesByEntry},
|
||||
next_config::load_next_config,
|
||||
next_dynamic::NextDynamicEntriesVc,
|
||||
next_dynamic::NextDynamicEntries,
|
||||
next_server::{get_server_chunking_context, get_server_compile_time_info},
|
||||
url_node::get_sorted_routes,
|
||||
{self},
|
||||
};
|
||||
use serde::Serialize;
|
||||
use turbo_tasks::{
|
||||
graph::{AdjacencyMap, GraphTraversal},
|
||||
CollectiblesSource, CompletionVc, CompletionsVc, RawVc, TransientInstance, TransientValue,
|
||||
TryJoinIterExt,
|
||||
Completion, Completions, TransientInstance, TransientValue, TryJoinIterExt, Vc,
|
||||
};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::{
|
||||
rebase, DiskFileSystemVc, FileContent, FileSystem, FileSystemPath, FileSystemPathVc,
|
||||
FileSystemVc,
|
||||
},
|
||||
turbo::tasks_fs::{rebase, DiskFileSystem, FileContent, FileSystem, FileSystemPath},
|
||||
turbopack::{
|
||||
build::BuildChunkingContextVc,
|
||||
cli_utils::issue::{ConsoleUiVc, LogOptions},
|
||||
build::BuildChunkingContext,
|
||||
cli_utils::issue::{ConsoleUi, LogOptions},
|
||||
core::{
|
||||
asset::{Asset, AssetVc, AssetsVc},
|
||||
asset::{Asset, Assets},
|
||||
chunk::ChunkingContext,
|
||||
environment::ServerAddrVc,
|
||||
issue::{IssueReporter, IssueReporterVc, IssueSeverity, IssueVc},
|
||||
output::{OutputAssetVc, OutputAssetsVc},
|
||||
environment::ServerAddr,
|
||||
issue::{IssueContextExt, IssueReporter, IssueSeverity},
|
||||
output::{OutputAsset, OutputAssets},
|
||||
reference::AssetReference,
|
||||
virtual_fs::VirtualFileSystemVc,
|
||||
virtual_fs::VirtualFileSystem,
|
||||
},
|
||||
dev::DevChunkingContextVc,
|
||||
dev::DevChunkingContext,
|
||||
ecmascript::utils::StringifyJs,
|
||||
env::dotenv::load_env,
|
||||
node::execution_context::ExecutionContextVc,
|
||||
node::execution_context::ExecutionContext,
|
||||
turbopack::evaluate_context::node_build_environment,
|
||||
},
|
||||
};
|
||||
|
@ -62,7 +58,7 @@ use crate::{
|
|||
};
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Result<CompletionVc> {
|
||||
pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Result<Vc<Completion>> {
|
||||
let project_root = options
|
||||
.dir
|
||||
.as_ref()
|
||||
|
@ -84,7 +80,8 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
};
|
||||
|
||||
let browserslist_query = "last 1 Chrome versions, last 1 Firefox versions, last 1 Safari \
|
||||
versions, last 1 Edge versions";
|
||||
versions, last 1 Edge versions"
|
||||
.to_string();
|
||||
|
||||
let log_options = LogOptions {
|
||||
project_dir: PathBuf::from(project_root.clone()),
|
||||
|
@ -94,47 +91,48 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
log_level: options.log_level.unwrap_or(IssueSeverity::Warning),
|
||||
};
|
||||
|
||||
let issue_reporter: IssueReporterVc =
|
||||
ConsoleUiVc::new(TransientInstance::new(log_options)).into();
|
||||
let node_fs = node_fs(&project_root, issue_reporter);
|
||||
let node_root = node_fs.root().join(".next");
|
||||
let client_fs = client_fs(&project_root, issue_reporter);
|
||||
let client_root = client_fs.root().join(".next");
|
||||
let issue_reporter: Vc<Box<dyn IssueReporter>> =
|
||||
Vc::upcast(ConsoleUi::new(TransientInstance::new(log_options)));
|
||||
let node_fs = node_fs(project_root.clone(), issue_reporter);
|
||||
let node_root = node_fs.root().join(".next".to_string());
|
||||
let client_fs = client_fs(project_root.clone(), issue_reporter);
|
||||
let client_root = client_fs.root().join(".next".to_string());
|
||||
// TODO(alexkirsz) This should accept a URL for assetPrefix.
|
||||
// let client_public_fs = VirtualFileSystemVc::new();
|
||||
// let client_public_fs = VirtualFileSystem::new();
|
||||
// let client_public_root = client_public_fs.root();
|
||||
let workspace_fs = workspace_fs(&workspace_root, issue_reporter);
|
||||
let workspace_fs = workspace_fs(workspace_root.clone(), issue_reporter);
|
||||
let project_relative = project_root.strip_prefix(&workspace_root).unwrap();
|
||||
let project_relative = project_relative
|
||||
.strip_prefix(MAIN_SEPARATOR)
|
||||
.unwrap_or(project_relative)
|
||||
.replace(MAIN_SEPARATOR, "/");
|
||||
let project_root = workspace_fs.root().join(&project_relative);
|
||||
let project_root = workspace_fs.root().join(project_relative);
|
||||
|
||||
let node_root_ref = node_root.await?;
|
||||
|
||||
let node_execution_chunking_context = DevChunkingContextVc::builder(
|
||||
project_root,
|
||||
node_root,
|
||||
node_root.join("chunks"),
|
||||
node_root.join("assets"),
|
||||
node_build_environment(),
|
||||
)
|
||||
.build()
|
||||
.into();
|
||||
let node_execution_chunking_context = Vc::upcast(
|
||||
DevChunkingContext::builder(
|
||||
project_root,
|
||||
node_root,
|
||||
node_root.join("chunks".to_string()),
|
||||
node_root.join("assets".to_string()),
|
||||
node_build_environment(),
|
||||
)
|
||||
.build(),
|
||||
);
|
||||
|
||||
let env = load_env(project_root);
|
||||
|
||||
let execution_context =
|
||||
ExecutionContextVc::new(project_root, node_execution_chunking_context, env);
|
||||
let next_config = load_next_config(execution_context.with_layer("next_config"));
|
||||
ExecutionContext::new(project_root, node_execution_chunking_context, env);
|
||||
let next_config = load_next_config(execution_context.with_layer("next_config".to_string()));
|
||||
|
||||
let mode = NextMode::Build;
|
||||
let client_compile_time_info = get_client_compile_time_info(mode, browserslist_query);
|
||||
let server_compile_time_info = get_server_compile_time_info(mode, env, ServerAddrVc::empty());
|
||||
let server_compile_time_info = get_server_compile_time_info(mode, env, ServerAddr::empty());
|
||||
|
||||
// TODO(alexkirsz) Pages should build their own routes, outside of a FS.
|
||||
let next_router_fs = VirtualFileSystemVc::new().as_file_system();
|
||||
let next_router_fs = Vc::upcast::<Box<dyn FileSystem>>(VirtualFileSystem::new());
|
||||
let next_router_root = next_router_fs.root();
|
||||
let page_entries = get_page_entries(
|
||||
next_router_root,
|
||||
|
@ -169,12 +167,8 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
.try_join()
|
||||
.await?;
|
||||
|
||||
let app_client_references_by_entry = ClientReferencesByEntryVc::new(AssetsVc::cell(
|
||||
app_rsc_entries
|
||||
.iter()
|
||||
.copied()
|
||||
.map(|entry| entry.into())
|
||||
.collect(),
|
||||
let app_client_references_by_entry = ClientReferencesByEntry::new(Vc::cell(
|
||||
app_rsc_entries.iter().copied().map(Vc::upcast).collect(),
|
||||
))
|
||||
.await?;
|
||||
|
||||
|
@ -228,12 +222,8 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
.collect();
|
||||
|
||||
// TODO(alexkirsz) Handle dynamic entries and dynamic chunks.
|
||||
let _dynamic_entries = NextDynamicEntriesVc::from_entries(AssetsVc::cell(
|
||||
all_node_entries
|
||||
.iter()
|
||||
.copied()
|
||||
.map(|entry| entry.into())
|
||||
.collect(),
|
||||
let _dynamic_entries = NextDynamicEntries::from_entries(Vc::cell(
|
||||
all_node_entries.iter().copied().map(Vc::upcast).collect(),
|
||||
))
|
||||
.await?;
|
||||
|
||||
|
@ -258,11 +248,11 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
);
|
||||
// TODO(alexkirsz) This should be the same chunking context. The layer should
|
||||
// be applied on the AssetContext level instead.
|
||||
let rsc_chunking_context = server_chunking_context.with_layer("rsc");
|
||||
let ssr_chunking_context = server_chunking_context.with_layer("ssr");
|
||||
let rsc_chunking_context = server_chunking_context.with_layer("rsc".to_string());
|
||||
let ssr_chunking_context = server_chunking_context.with_layer("ssr".to_string());
|
||||
let (Some(rsc_chunking_context), Some(ssr_chunking_context)) = (
|
||||
BuildChunkingContextVc::resolve_from(rsc_chunking_context).await?,
|
||||
BuildChunkingContextVc::resolve_from(ssr_chunking_context).await?,
|
||||
Vc::try_resolve_downcast_type::<BuildChunkingContext>(rsc_chunking_context).await?,
|
||||
Vc::try_resolve_downcast_type::<BuildChunkingContext>(ssr_chunking_context).await?,
|
||||
) else {
|
||||
bail!("with_layer should not change the type of the chunking context");
|
||||
};
|
||||
|
@ -270,18 +260,18 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
let mut all_chunks = vec![];
|
||||
|
||||
let mut build_manifest: BuildManifest = Default::default();
|
||||
let build_manifest_path = client_root.join("build-manifest.json");
|
||||
let build_manifest_path = client_root.join("build-manifest.json".to_string());
|
||||
|
||||
// This ensures that the _next prefix is properly stripped from all client paths
|
||||
// in manifests. It will be added back on the client through the chunk_base_path
|
||||
// mechanism.
|
||||
let client_relative_path = client_root.join("_next");
|
||||
let client_relative_path = client_root.join("_next".to_string());
|
||||
let client_relative_path_ref = client_relative_path.await?;
|
||||
|
||||
// PAGE CHUNKING
|
||||
|
||||
let mut pages_manifest: PagesManifest = Default::default();
|
||||
let pages_manifest_path = node_root.join("server/pages-manifest.json");
|
||||
let pages_manifest_path = node_root.join("server/pages-manifest.json".to_string());
|
||||
let pages_manifest_dir_path = pages_manifest_path.parent().await?;
|
||||
|
||||
compute_page_entries_chunks(
|
||||
|
@ -300,10 +290,10 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
// APP CHUNKING
|
||||
|
||||
let mut app_build_manifest = AppBuildManifest::default();
|
||||
let app_build_manifest_path = client_root.join("app-build-manifest.json");
|
||||
let app_build_manifest_path = client_root.join("app-build-manifest.json".to_string());
|
||||
|
||||
let mut app_paths_manifest = AppPathsManifest::default();
|
||||
let app_paths_manifest_path = node_root.join("server/app-paths-manifest.json");
|
||||
let app_paths_manifest_path = node_root.join("server/app-paths-manifest.json".to_string());
|
||||
let app_paths_manifest_dir_path = app_paths_manifest_path.parent().await?;
|
||||
|
||||
// APP CLIENT REFERENCES CHUNKING
|
||||
|
@ -325,7 +315,7 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
&app_client_references_chunks,
|
||||
rsc_chunking_context,
|
||||
client_chunking_context,
|
||||
ssr_chunking_context.into(),
|
||||
Vc::upcast(ssr_chunking_context),
|
||||
node_root,
|
||||
&client_relative_path_ref,
|
||||
&app_paths_manifest_dir_path,
|
||||
|
@ -343,7 +333,7 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
|
||||
let ssg_manifest_path = format!("static/{build_id}/_ssgManifest.js");
|
||||
|
||||
let ssg_manifest_fs_path = node_root.join(&ssg_manifest_path);
|
||||
let ssg_manifest_fs_path = node_root.join(ssg_manifest_path.clone());
|
||||
completions.push(
|
||||
ssg_manifest_fs_path.write(
|
||||
FileContent::Content(
|
||||
|
@ -393,7 +383,7 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
|
||||
let client_manifest_path = format!("static/{build_id}/_buildManifest.js");
|
||||
|
||||
let client_manifest_fs_path = node_root.join(&client_manifest_path);
|
||||
let client_manifest_fs_path = node_root.join(client_manifest_path.clone());
|
||||
completions.push(
|
||||
client_manifest_fs_path.write(
|
||||
FileContent::Content(
|
||||
|
@ -422,23 +412,23 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
// experimental-edge pages?
|
||||
completions.push(write_manifest(
|
||||
MiddlewaresManifest::default(),
|
||||
node_root.join("server/middleware-manifest.json"),
|
||||
node_root.join("server/middleware-manifest.json".to_string()),
|
||||
)?);
|
||||
completions.push(write_manifest(
|
||||
NextFontManifest::default(),
|
||||
node_root.join("server/next-font-manifest.json"),
|
||||
node_root.join("server/next-font-manifest.json".to_string()),
|
||||
)?);
|
||||
completions.push(write_manifest(
|
||||
FontManifest::default(),
|
||||
node_root.join("server/font-manifest.json"),
|
||||
node_root.join("server/font-manifest.json".to_string()),
|
||||
)?);
|
||||
completions.push(write_manifest(
|
||||
ServerReferenceManifest::default(),
|
||||
node_root.join("server/server-reference-manifest.json"),
|
||||
node_root.join("server/server-reference-manifest.json".to_string()),
|
||||
)?);
|
||||
completions.push(write_manifest(
|
||||
ReactLoadableManifest::default(),
|
||||
node_root.join("react-loadable-manifest.json"),
|
||||
node_root.join("react-loadable-manifest.json".to_string()),
|
||||
)?);
|
||||
|
||||
completions.push(
|
||||
|
@ -451,45 +441,49 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
|||
.await?,
|
||||
);
|
||||
|
||||
Ok(CompletionsVc::all(completions))
|
||||
Ok(Completions::all(completions))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn workspace_fs(
|
||||
workspace_root: &str,
|
||||
issue_reporter: IssueReporterVc,
|
||||
) -> Result<FileSystemVc> {
|
||||
let disk_fs = DiskFileSystemVc::new("workspace".to_string(), workspace_root.to_string());
|
||||
workspace_root: String,
|
||||
issue_reporter: Vc<Box<dyn IssueReporter>>,
|
||||
) -> Result<Vc<Box<dyn FileSystem>>> {
|
||||
let disk_fs = DiskFileSystem::new("workspace".to_string(), workspace_root.to_string());
|
||||
handle_issues(disk_fs, issue_reporter).await?;
|
||||
Ok(disk_fs.into())
|
||||
Ok(Vc::upcast(disk_fs))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn node_fs(node_root: &str, issue_reporter: IssueReporterVc) -> Result<FileSystemVc> {
|
||||
let disk_fs = DiskFileSystemVc::new("node".to_string(), node_root.to_string());
|
||||
async fn node_fs(
|
||||
node_root: String,
|
||||
issue_reporter: Vc<Box<dyn IssueReporter>>,
|
||||
) -> Result<Vc<Box<dyn FileSystem>>> {
|
||||
let disk_fs = DiskFileSystem::new("node".to_string(), node_root.to_string());
|
||||
handle_issues(disk_fs, issue_reporter).await?;
|
||||
Ok(disk_fs.into())
|
||||
Ok(Vc::upcast(disk_fs))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn client_fs(client_root: &str, issue_reporter: IssueReporterVc) -> Result<FileSystemVc> {
|
||||
let disk_fs = DiskFileSystemVc::new("client".to_string(), client_root.to_string());
|
||||
async fn client_fs(
|
||||
client_root: String,
|
||||
issue_reporter: Vc<Box<dyn IssueReporter>>,
|
||||
) -> Result<Vc<Box<dyn FileSystem>>> {
|
||||
let disk_fs = DiskFileSystem::new("client".to_string(), client_root.to_string());
|
||||
handle_issues(disk_fs, issue_reporter).await?;
|
||||
Ok(disk_fs.into())
|
||||
Ok(Vc::upcast(disk_fs))
|
||||
}
|
||||
|
||||
async fn handle_issues<T: Into<RawVc> + CollectiblesSource + Copy>(
|
||||
source: T,
|
||||
issue_reporter: IssueReporterVc,
|
||||
) -> Result<()> {
|
||||
let issues = IssueVc::peek_issues_with_path(source)
|
||||
async fn handle_issues<T>(source: Vc<T>, issue_reporter: Vc<Box<dyn IssueReporter>>) -> Result<()> {
|
||||
let issues = source
|
||||
.peek_issues_with_path()
|
||||
.await?
|
||||
.strongly_consistent()
|
||||
.await?;
|
||||
|
||||
let has_fatal = issue_reporter.report_issues(
|
||||
TransientInstance::new(issues.clone()),
|
||||
TransientValue::new(source.into()),
|
||||
TransientValue::new(source.node),
|
||||
);
|
||||
|
||||
if *has_fatal.await? {
|
||||
|
@ -502,31 +496,31 @@ async fn handle_issues<T: Into<RawVc> + CollectiblesSource + Copy>(
|
|||
/// Emits all assets transitively reachable from the given chunks, that are
|
||||
/// inside the node root or the client root.
|
||||
async fn emit_all_assets(
|
||||
chunks: Vec<OutputAssetVc>,
|
||||
chunks: Vec<Vc<Box<dyn OutputAsset>>>,
|
||||
node_root: &FileSystemPath,
|
||||
client_relative_path: FileSystemPathVc,
|
||||
client_output_path: FileSystemPathVc,
|
||||
) -> Result<CompletionVc> {
|
||||
let all_assets = all_assets_from_entries(OutputAssetsVc::cell(chunks)).await?;
|
||||
Ok(CompletionsVc::all(
|
||||
client_relative_path: Vc<FileSystemPath>,
|
||||
client_output_path: Vc<FileSystemPath>,
|
||||
) -> Result<Vc<Completion>> {
|
||||
let all_assets = all_assets_from_entries(Vc::cell(chunks)).await?;
|
||||
Ok(Completions::all(
|
||||
all_assets
|
||||
.iter()
|
||||
.copied()
|
||||
.map(|asset| async move {
|
||||
if asset.ident().path().await?.is_inside(node_root) {
|
||||
if asset.ident().path().await?.is_inside_ref(node_root) {
|
||||
return Ok(emit(asset));
|
||||
} else if asset
|
||||
.ident()
|
||||
.path()
|
||||
.await?
|
||||
.is_inside(&*client_relative_path.await?)
|
||||
.is_inside_ref(&*client_relative_path.await?)
|
||||
{
|
||||
// Client assets are emitted to the client output path, which is prefixed with
|
||||
// _next. We need to rebase them to remove that prefix.
|
||||
return Ok(emit_rebase(asset, client_relative_path, client_output_path));
|
||||
}
|
||||
|
||||
Ok(CompletionVc::immutable())
|
||||
Ok(Completion::immutable())
|
||||
})
|
||||
.try_join()
|
||||
.await?,
|
||||
|
@ -534,12 +528,16 @@ async fn emit_all_assets(
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn emit(asset: AssetVc) -> CompletionVc {
|
||||
fn emit(asset: Vc<Box<dyn Asset>>) -> Vc<Completion> {
|
||||
asset.content().write(asset.ident().path())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn emit_rebase(asset: AssetVc, from: FileSystemPathVc, to: FileSystemPathVc) -> CompletionVc {
|
||||
fn emit_rebase(
|
||||
asset: Vc<Box<dyn Asset>>,
|
||||
from: Vc<FileSystemPath>,
|
||||
to: Vc<FileSystemPath>,
|
||||
) -> Vc<Completion> {
|
||||
asset
|
||||
.content()
|
||||
.write(rebase(asset.ident().path(), from, to))
|
||||
|
@ -548,12 +546,12 @@ fn emit_rebase(asset: AssetVc, from: FileSystemPathVc, to: FileSystemPathVc) ->
|
|||
/// Walks the asset graph from multiple assets and collect all referenced
|
||||
/// assets.
|
||||
#[turbo_tasks::function]
|
||||
async fn all_assets_from_entries(entries: OutputAssetsVc) -> Result<AssetsVc> {
|
||||
Ok(AssetsVc::cell(
|
||||
async fn all_assets_from_entries(entries: Vc<OutputAssets>) -> Result<Vc<Assets>> {
|
||||
Ok(Vc::cell(
|
||||
AdjacencyMap::new()
|
||||
.skip_duplicates()
|
||||
.visit(
|
||||
entries.await?.iter().copied().map(Into::into),
|
||||
entries.await?.iter().copied().map(Vc::upcast),
|
||||
get_referenced_assets,
|
||||
)
|
||||
.await
|
||||
|
@ -565,7 +563,9 @@ async fn all_assets_from_entries(entries: OutputAssetsVc) -> Result<AssetsVc> {
|
|||
}
|
||||
|
||||
/// Computes the list of all chunk children of a given chunk.
|
||||
async fn get_referenced_assets(asset: AssetVc) -> Result<impl Iterator<Item = AssetVc> + Send> {
|
||||
async fn get_referenced_assets(
|
||||
asset: Vc<Box<dyn Asset>>,
|
||||
) -> Result<impl Iterator<Item = Vc<Box<dyn Asset>>> + Send> {
|
||||
Ok(asset
|
||||
.references()
|
||||
.await?
|
||||
|
@ -582,7 +582,7 @@ async fn get_referenced_assets(asset: AssetVc) -> Result<impl Iterator<Item = As
|
|||
|
||||
/// Writes a manifest to disk. This consumes the manifest to ensure we don't
|
||||
/// write to it afterwards.
|
||||
fn write_manifest<T>(manifest: T, manifest_path: FileSystemPathVc) -> Result<CompletionVc>
|
||||
fn write_manifest<T>(manifest: T, manifest_path: Vc<FileSystemPath>) -> Result<Vc<Completion>>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
|
|
|
@ -6,45 +6,38 @@ use next_core::{
|
|||
get_client_module_options_context, get_client_resolve_options_context,
|
||||
get_client_runtime_entries, ClientContextType,
|
||||
},
|
||||
next_config::NextConfigVc,
|
||||
next_dynamic::NextDynamicTransitionVc,
|
||||
next_config::NextConfig,
|
||||
next_dynamic::NextDynamicTransition,
|
||||
next_server::{
|
||||
get_server_module_options_context, get_server_resolve_options_context,
|
||||
get_server_runtime_entries, ServerContextType,
|
||||
},
|
||||
pages_structure::{
|
||||
find_pages_structure, PagesDirectoryStructure, PagesDirectoryStructureVc, PagesStructure,
|
||||
PagesStructureItem, PagesStructureVc,
|
||||
find_pages_structure, PagesDirectoryStructure, PagesStructure, PagesStructureItem,
|
||||
},
|
||||
pathname_for_path, PathType,
|
||||
};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::{
|
||||
tasks::{primitives::StringVc, Value},
|
||||
tasks_env::ProcessEnvVc,
|
||||
tasks_fs::{FileSystemPath, FileSystemPathVc},
|
||||
},
|
||||
turbo::{tasks::Value, tasks_env::ProcessEnv, tasks_fs::FileSystemPath},
|
||||
turbopack::{
|
||||
build::BuildChunkingContextVc,
|
||||
build::BuildChunkingContext,
|
||||
core::{
|
||||
asset::Asset,
|
||||
chunk::{ChunkableModule, ChunkingContext, EvaluatableAssetsVc},
|
||||
compile_time_info::CompileTimeInfoVc,
|
||||
context::{AssetContext, AssetContextVc},
|
||||
file_source::FileSourceVc,
|
||||
output::OutputAssetVc,
|
||||
chunk::{ChunkableModule, ChunkingContext, EvaluatableAssets},
|
||||
compile_time_info::CompileTimeInfo,
|
||||
context::AssetContext,
|
||||
file_source::FileSource,
|
||||
output::OutputAsset,
|
||||
reference_type::{EntryReferenceSubType, ReferenceType},
|
||||
source::SourceVc,
|
||||
source::Source,
|
||||
},
|
||||
ecmascript::{
|
||||
chunk::{EcmascriptChunkPlaceableVc, EcmascriptChunkingContextVc},
|
||||
EcmascriptModuleAssetVc,
|
||||
},
|
||||
node::execution_context::ExecutionContextVc,
|
||||
turbopack::{
|
||||
transition::{ContextTransitionVc, TransitionsByNameVc},
|
||||
ModuleAssetContextVc,
|
||||
chunk::{EcmascriptChunkPlaceable, EcmascriptChunkingContext},
|
||||
EcmascriptModuleAsset,
|
||||
},
|
||||
node::execution_context::ExecutionContext,
|
||||
turbopack::{transition::ContextTransition, ModuleAssetContext},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -52,22 +45,22 @@ use crate::manifests::{BuildManifest, PagesManifest};
|
|||
|
||||
#[turbo_tasks::value]
|
||||
pub struct PageEntries {
|
||||
pub entries: Vec<PageEntryVc>,
|
||||
pub ssr_runtime_entries: EvaluatableAssetsVc,
|
||||
pub client_runtime_entries: EvaluatableAssetsVc,
|
||||
pub entries: Vec<Vc<PageEntry>>,
|
||||
pub ssr_runtime_entries: Vc<EvaluatableAssets>,
|
||||
pub client_runtime_entries: Vc<EvaluatableAssets>,
|
||||
}
|
||||
|
||||
/// Computes all the page entries within the given project root.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_page_entries(
|
||||
next_router_root: FileSystemPathVc,
|
||||
project_root: FileSystemPathVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
env: ProcessEnvVc,
|
||||
client_compile_time_info: CompileTimeInfoVc,
|
||||
server_compile_time_info: CompileTimeInfoVc,
|
||||
next_config: NextConfigVc,
|
||||
) -> Result<PageEntriesVc> {
|
||||
next_router_root: Vc<FileSystemPath>,
|
||||
project_root: Vc<FileSystemPath>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
env: Vc<Box<dyn ProcessEnv>>,
|
||||
client_compile_time_info: Vc<CompileTimeInfo>,
|
||||
server_compile_time_info: Vc<CompileTimeInfo>,
|
||||
next_config: Vc<NextConfig>,
|
||||
) -> Result<Vc<PageEntries>> {
|
||||
let pages_structure = find_pages_structure(
|
||||
project_root,
|
||||
next_router_root,
|
||||
|
@ -77,7 +70,7 @@ pub async fn get_page_entries(
|
|||
let pages_dir = if let Some(pages) = pages_structure.await?.pages {
|
||||
pages.project_path().resolve().await?
|
||||
} else {
|
||||
project_root.join("pages")
|
||||
project_root.join("pages".to_string())
|
||||
};
|
||||
|
||||
let mode = NextMode::Build;
|
||||
|
@ -102,28 +95,27 @@ pub async fn get_page_entries(
|
|||
execution_context,
|
||||
);
|
||||
|
||||
let client_transition = ContextTransitionVc::new(
|
||||
let client_transition = ContextTransition::new(
|
||||
client_compile_time_info,
|
||||
client_module_options_context,
|
||||
client_resolve_options_context,
|
||||
);
|
||||
|
||||
let transitions = TransitionsByNameVc::cell(
|
||||
let transitions = Vc::cell(
|
||||
[(
|
||||
"next-dynamic".to_string(),
|
||||
NextDynamicTransitionVc::new(client_transition).into(),
|
||||
Vc::upcast(NextDynamicTransition::new(client_transition)),
|
||||
)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let client_module_context: AssetContextVc = ModuleAssetContextVc::new(
|
||||
let client_module_context: Vc<Box<dyn AssetContext>> = Vc::upcast(ModuleAssetContext::new(
|
||||
transitions,
|
||||
client_compile_time_info,
|
||||
client_module_options_context,
|
||||
client_resolve_options_context,
|
||||
)
|
||||
.into();
|
||||
));
|
||||
|
||||
let client_runtime_entries = get_client_runtime_entries(
|
||||
project_root,
|
||||
|
@ -150,13 +142,12 @@ pub async fn get_page_entries(
|
|||
next_config,
|
||||
);
|
||||
|
||||
let ssr_module_context = ModuleAssetContextVc::new(
|
||||
let ssr_module_context = Vc::upcast(ModuleAssetContext::new(
|
||||
transitions,
|
||||
server_compile_time_info,
|
||||
ssr_module_options_context,
|
||||
ssr_resolve_options_context,
|
||||
)
|
||||
.into();
|
||||
));
|
||||
|
||||
let ssr_runtime_entries =
|
||||
get_server_runtime_entries(project_root, env, ssr_ty, mode, next_config);
|
||||
|
@ -179,11 +170,11 @@ pub async fn get_page_entries(
|
|||
}
|
||||
|
||||
async fn get_page_entries_for_root_directory(
|
||||
ssr_module_context: AssetContextVc,
|
||||
client_module_context: AssetContextVc,
|
||||
pages_structure: PagesStructureVc,
|
||||
next_router_root: FileSystemPathVc,
|
||||
) -> Result<Vec<PageEntryVc>> {
|
||||
ssr_module_context: Vc<Box<dyn AssetContext>>,
|
||||
client_module_context: Vc<Box<dyn AssetContext>>,
|
||||
pages_structure: Vc<PagesStructure>,
|
||||
next_router_root: Vc<FileSystemPath>,
|
||||
) -> Result<Vec<Vc<PageEntry>>> {
|
||||
let PagesStructure {
|
||||
app,
|
||||
document,
|
||||
|
@ -199,7 +190,7 @@ async fn get_page_entries_for_root_directory(
|
|||
entries.push(get_page_entry_for_file(
|
||||
ssr_module_context,
|
||||
client_module_context,
|
||||
FileSourceVc::new(app.project_path).into(),
|
||||
Vc::upcast(FileSource::new(app.project_path)),
|
||||
next_router_root,
|
||||
app.next_router_path,
|
||||
));
|
||||
|
@ -209,7 +200,7 @@ async fn get_page_entries_for_root_directory(
|
|||
entries.push(get_page_entry_for_file(
|
||||
ssr_module_context,
|
||||
client_module_context,
|
||||
FileSourceVc::new(document.project_path).into(),
|
||||
Vc::upcast(FileSource::new(document.project_path)),
|
||||
next_router_root,
|
||||
document.next_router_path,
|
||||
));
|
||||
|
@ -220,7 +211,7 @@ async fn get_page_entries_for_root_directory(
|
|||
entries.push(get_page_entry_for_file(
|
||||
ssr_module_context,
|
||||
client_module_context,
|
||||
FileSourceVc::new(error.project_path).into(),
|
||||
Vc::upcast(FileSource::new(error.project_path)),
|
||||
next_router_root,
|
||||
error.next_router_path,
|
||||
));
|
||||
|
@ -252,11 +243,11 @@ async fn get_page_entries_for_root_directory(
|
|||
|
||||
#[async_recursion::async_recursion]
|
||||
async fn get_page_entries_for_directory(
|
||||
ssr_module_context: AssetContextVc,
|
||||
client_module_context: AssetContextVc,
|
||||
pages_structure: PagesDirectoryStructureVc,
|
||||
next_router_root: FileSystemPathVc,
|
||||
entries: &mut Vec<PageEntryVc>,
|
||||
ssr_module_context: Vc<Box<dyn AssetContext>>,
|
||||
client_module_context: Vc<Box<dyn AssetContext>>,
|
||||
pages_structure: Vc<PagesDirectoryStructure>,
|
||||
next_router_root: Vc<FileSystemPath>,
|
||||
entries: &mut Vec<Vc<PageEntry>>,
|
||||
) -> Result<()> {
|
||||
let PagesDirectoryStructure {
|
||||
ref items,
|
||||
|
@ -273,7 +264,7 @@ async fn get_page_entries_for_directory(
|
|||
entries.push(get_page_entry_for_file(
|
||||
ssr_module_context,
|
||||
client_module_context,
|
||||
FileSourceVc::new(project_path).into(),
|
||||
Vc::upcast(FileSource::new(project_path)),
|
||||
next_router_root,
|
||||
next_router_path,
|
||||
));
|
||||
|
@ -297,21 +288,21 @@ async fn get_page_entries_for_directory(
|
|||
#[turbo_tasks::value]
|
||||
pub struct PageEntry {
|
||||
/// The pathname of the page.
|
||||
pub pathname: StringVc,
|
||||
pub pathname: Vc<String>,
|
||||
/// The Node.js SSR entry module asset.
|
||||
pub ssr_module: EcmascriptChunkPlaceableVc,
|
||||
pub ssr_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
/// The client entry module asset.
|
||||
pub client_module: EcmascriptModuleAssetVc,
|
||||
pub client_module: Vc<EcmascriptModuleAsset>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn get_page_entry_for_file(
|
||||
ssr_module_context: AssetContextVc,
|
||||
client_module_context: AssetContextVc,
|
||||
source: SourceVc,
|
||||
next_router_root: FileSystemPathVc,
|
||||
next_router_path: FileSystemPathVc,
|
||||
) -> Result<PageEntryVc> {
|
||||
ssr_module_context: Vc<Box<dyn AssetContext>>,
|
||||
client_module_context: Vc<Box<dyn AssetContext>>,
|
||||
source: Vc<Box<dyn Source>>,
|
||||
next_router_root: Vc<FileSystemPath>,
|
||||
next_router_path: Vc<FileSystemPath>,
|
||||
) -> Result<Vc<PageEntry>> {
|
||||
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
||||
|
||||
let pathname = pathname_for_path(next_router_root, next_router_path, PathType::Page);
|
||||
|
@ -320,11 +311,15 @@ async fn get_page_entry_for_file(
|
|||
|
||||
let client_module = create_page_loader_entry_module(client_module_context, source, pathname);
|
||||
|
||||
let Some(client_module) = EcmascriptModuleAssetVc::resolve_from(client_module).await? else {
|
||||
let Some(client_module) =
|
||||
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(client_module).await?
|
||||
else {
|
||||
bail!("expected an ECMAScript module asset");
|
||||
};
|
||||
|
||||
let Some(ssr_module) = EcmascriptChunkPlaceableVc::resolve_from(ssr_module).await? else {
|
||||
let Some(ssr_module) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(ssr_module).await?
|
||||
else {
|
||||
bail!("expected an ECMAScript chunk placeable asset");
|
||||
};
|
||||
|
||||
|
@ -338,23 +333,23 @@ async fn get_page_entry_for_file(
|
|||
|
||||
/// Computes the pathname for a given path.
|
||||
#[turbo_tasks::function]
|
||||
async fn pathname_from_path(next_router_path: FileSystemPathVc) -> Result<StringVc> {
|
||||
async fn pathname_from_path(next_router_path: Vc<FileSystemPath>) -> Result<Vc<String>> {
|
||||
let pathname = next_router_path.await?;
|
||||
Ok(StringVc::cell(pathname.path.clone()))
|
||||
Ok(Vc::cell(pathname.path.clone()))
|
||||
}
|
||||
|
||||
/// Computes the chunks of page entries, adds their paths to the corresponding
|
||||
/// manifests, and pushes the assets to the `all_chunks` vec.
|
||||
pub async fn compute_page_entries_chunks(
|
||||
page_entries: &PageEntries,
|
||||
client_chunking_context: EcmascriptChunkingContextVc,
|
||||
ssr_chunking_context: BuildChunkingContextVc,
|
||||
node_root: FileSystemPathVc,
|
||||
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
ssr_chunking_context: Vc<BuildChunkingContext>,
|
||||
node_root: Vc<FileSystemPath>,
|
||||
pages_manifest_dir_path: &FileSystemPath,
|
||||
client_relative_path: &FileSystemPath,
|
||||
pages_manifest: &mut PagesManifest,
|
||||
build_manifest: &mut BuildManifest,
|
||||
all_chunks: &mut Vec<OutputAssetVc>,
|
||||
all_chunks: &mut Vec<Vc<Box<dyn OutputAsset>>>,
|
||||
) -> Result<()> {
|
||||
for page_entry in page_entries.entries.iter() {
|
||||
let page_entry = page_entry.await?;
|
||||
|
@ -362,7 +357,7 @@ pub async fn compute_page_entries_chunks(
|
|||
let asset_path: String = get_asset_path_from_pathname(&pathname, ".js");
|
||||
|
||||
let ssr_entry_chunk = ssr_chunking_context.entry_chunk(
|
||||
node_root.join(&format!("server/pages/{asset_path}")),
|
||||
node_root.join(format!("server/pages/{asset_path}")),
|
||||
page_entry.ssr_module,
|
||||
page_entries.ssr_runtime_entries,
|
||||
);
|
||||
|
@ -377,13 +372,13 @@ pub async fn compute_page_entries_chunks(
|
|||
|
||||
let client_entry_chunk = page_entry
|
||||
.client_module
|
||||
.as_root_chunk(client_chunking_context.into());
|
||||
.as_root_chunk(Vc::upcast(client_chunking_context));
|
||||
|
||||
let client_chunks = client_chunking_context.evaluated_chunk_group(
|
||||
client_entry_chunk,
|
||||
page_entries
|
||||
.client_runtime_entries
|
||||
.with_entry(page_entry.client_module.into()),
|
||||
.with_entry(Vc::upcast(page_entry.client_module)),
|
||||
);
|
||||
|
||||
let build_manifest_pages_entry = build_manifest
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
"check": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.3",
|
||||
"@vercel/turbopack-node": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230713.3",
|
||||
"@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230716.2",
|
||||
"@vercel/turbopack-node": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230716.2",
|
||||
"anser": "^2.1.1",
|
||||
"css.escape": "^1.5.1",
|
||||
"next": "*",
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use turbopack_binding::turbo::tasks_fs::FileSystemPathVc;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbo::tasks_fs::FileSystemPath;
|
||||
|
||||
pub mod next_server_component_transition;
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct LayoutSegment {
|
||||
pub files: HashMap<String, FileSystemPathVc>,
|
||||
pub target: FileSystemPathVc,
|
||||
pub files: HashMap<String, Vc<FileSystemPath>>,
|
||||
pub target: Vc<FileSystemPath>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub struct LayoutSegments(Vec<LayoutSegmentVc>);
|
||||
pub struct LayoutSegments(Vec<Vc<LayoutSegment>>);
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::FileSystemPathVc,
|
||||
turbo::tasks_fs::FileSystemPath,
|
||||
turbopack::{
|
||||
core::{compile_time_info::CompileTimeInfoVc, module::ModuleVc},
|
||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
||||
core::{compile_time_info::CompileTimeInfo, module::Module},
|
||||
ecmascript::chunk::EcmascriptChunkPlaceable,
|
||||
turbopack::{
|
||||
module_options::ModuleOptionsContextVc,
|
||||
resolve_options_context::ResolveOptionsContextVc,
|
||||
transition::{Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
module_options::ModuleOptionsContext, resolve_options_context::ResolveOptionsContext,
|
||||
transition::Transition, ModuleAssetContext,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -20,10 +19,10 @@ use crate::next_client_component::{
|
|||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextServerComponentTransition {
|
||||
pub rsc_compile_time_info: CompileTimeInfoVc,
|
||||
pub rsc_module_options_context: ModuleOptionsContextVc,
|
||||
pub rsc_resolve_options_context: ResolveOptionsContextVc,
|
||||
pub server_root: FileSystemPathVc,
|
||||
pub rsc_compile_time_info: Vc<CompileTimeInfo>,
|
||||
pub rsc_module_options_context: Vc<ModuleOptionsContext>,
|
||||
pub rsc_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||
pub server_root: Vc<FileSystemPath>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
|
@ -31,48 +30,52 @@ impl Transition for NextServerComponentTransition {
|
|||
#[turbo_tasks::function]
|
||||
fn process_compile_time_info(
|
||||
&self,
|
||||
_compile_time_info: CompileTimeInfoVc,
|
||||
) -> CompileTimeInfoVc {
|
||||
_compile_time_info: Vc<CompileTimeInfo>,
|
||||
) -> Vc<CompileTimeInfo> {
|
||||
self.rsc_compile_time_info
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_module_options_context(
|
||||
&self,
|
||||
_context: ModuleOptionsContextVc,
|
||||
) -> ModuleOptionsContextVc {
|
||||
_context: Vc<ModuleOptionsContext>,
|
||||
) -> Vc<ModuleOptionsContext> {
|
||||
self.rsc_module_options_context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_resolve_options_context(
|
||||
&self,
|
||||
_context: ResolveOptionsContextVc,
|
||||
) -> ResolveOptionsContextVc {
|
||||
_context: Vc<ResolveOptionsContext>,
|
||||
) -> Vc<ResolveOptionsContext> {
|
||||
self.rsc_resolve_options_context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn process_module(
|
||||
&self,
|
||||
module: ModuleVc,
|
||||
_context: ModuleAssetContextVc,
|
||||
) -> Result<ModuleVc> {
|
||||
let Some(asset) = EcmascriptChunkPlaceableVc::resolve_from(module).await? else {
|
||||
module: Vc<Box<dyn Module>>,
|
||||
_context: Vc<ModuleAssetContext>,
|
||||
) -> Result<Vc<Box<dyn Module>>> {
|
||||
let Some(asset) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(module).await?
|
||||
else {
|
||||
bail!("Not an ecmascript module");
|
||||
};
|
||||
|
||||
Ok(WithChunkingContextScopeAsset {
|
||||
asset: WithClientChunksAsset {
|
||||
asset,
|
||||
// next.js code already adds _next prefix
|
||||
server_root: self.server_root.join("_next"),
|
||||
Ok(Vc::upcast(
|
||||
WithChunkingContextScopeAsset {
|
||||
asset: Vc::upcast(
|
||||
WithClientChunksAsset {
|
||||
asset,
|
||||
// next.js code already adds _next prefix
|
||||
server_root: self.server_root.join("_next".to_string()),
|
||||
}
|
||||
.cell(),
|
||||
),
|
||||
layer: "rsc".to_string(),
|
||||
}
|
||||
.cell()
|
||||
.into(),
|
||||
layer: "rsc".to_string(),
|
||||
}
|
||||
.cell()
|
||||
.into())
|
||||
.cell(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,28 +7,26 @@ use swc_core::{
|
|||
common::{source_map::Pos, Span, Spanned},
|
||||
ecma::ast::{Expr, Ident, Program},
|
||||
};
|
||||
use turbo_tasks::{primitives::StringVc, trace::TraceRawVcs, TryJoinIterExt};
|
||||
use turbo_tasks_fs::FileSystemPathVc;
|
||||
use turbo_tasks::{trace::TraceRawVcs, TryJoinIterExt, ValueDefault, Vc};
|
||||
use turbo_tasks_fs::FileSystemPath;
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
asset::{Asset, AssetVc},
|
||||
context::{AssetContext, AssetContextVc},
|
||||
file_source::FileSourceVc,
|
||||
ident::AssetIdentVc,
|
||||
issue::{
|
||||
Issue, IssueSeverity, IssueSeverityVc, IssueSourceVc, IssueVc, OptionIssueSourceVc,
|
||||
},
|
||||
module::ModuleVc,
|
||||
asset::Asset,
|
||||
context::AssetContext,
|
||||
file_source::FileSource,
|
||||
ident::AssetIdent,
|
||||
issue::{Issue, IssueExt, IssueSeverity, IssueSource, OptionIssueSource},
|
||||
module::Module,
|
||||
reference_type::{EcmaScriptModulesReferenceSubType, ReferenceType},
|
||||
},
|
||||
ecmascript::{
|
||||
analyzer::{graph::EvalContext, ConstantNumber, ConstantValue, JsValue},
|
||||
parse::ParseResult,
|
||||
EcmascriptModuleAssetVc,
|
||||
EcmascriptModuleAsset,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{app_structure::LoaderTreeVc, util::NextRuntime};
|
||||
use crate::{app_structure::LoaderTree, util::NextRuntime};
|
||||
|
||||
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug, TraceRawVcs, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
|
@ -75,9 +73,9 @@ pub struct NextSegmentConfig {
|
|||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextSegmentConfigVc {
|
||||
impl ValueDefault for NextSegmentConfig {
|
||||
#[turbo_tasks::function]
|
||||
pub fn default() -> Self {
|
||||
pub fn value_default() -> Vc<Self> {
|
||||
NextSegmentConfig::default().cell()
|
||||
}
|
||||
}
|
||||
|
@ -155,36 +153,36 @@ impl NextSegmentConfig {
|
|||
/// An issue that occurred while parsing the app segment config.
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextSegmentConfigParsingIssue {
|
||||
ident: AssetIdentVc,
|
||||
detail: StringVc,
|
||||
source: IssueSourceVc,
|
||||
ident: Vc<AssetIdent>,
|
||||
detail: Vc<String>,
|
||||
source: Vc<IssueSource>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Issue for NextSegmentConfigParsingIssue {
|
||||
#[turbo_tasks::function]
|
||||
fn severity(&self) -> IssueSeverityVc {
|
||||
fn severity(&self) -> Vc<IssueSeverity> {
|
||||
IssueSeverity::Warning.into()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn title(&self) -> StringVc {
|
||||
StringVc::cell("Unable to parse config export in source file".to_string())
|
||||
fn title(&self) -> Vc<String> {
|
||||
Vc::cell("Unable to parse config export in source file".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn category(&self) -> StringVc {
|
||||
StringVc::cell("parsing".to_string())
|
||||
fn category(&self) -> Vc<String> {
|
||||
Vc::cell("parsing".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn context(&self) -> FileSystemPathVc {
|
||||
fn context(&self) -> Vc<FileSystemPath> {
|
||||
self.ident.path()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn description(&self) -> StringVc {
|
||||
StringVc::cell(
|
||||
fn description(&self) -> Vc<String> {
|
||||
Vc::cell(
|
||||
"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(),
|
||||
|
@ -192,30 +190,32 @@ impl Issue for NextSegmentConfigParsingIssue {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn detail(&self) -> StringVc {
|
||||
fn detail(&self) -> Vc<String> {
|
||||
self.detail
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn documentation_link(&self) -> StringVc {
|
||||
StringVc::cell(
|
||||
fn documentation_link(&self) -> Vc<String> {
|
||||
Vc::cell(
|
||||
"https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config"
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn source(&self) -> OptionIssueSourceVc {
|
||||
OptionIssueSourceVc::some(self.source)
|
||||
fn source(&self) -> Vc<OptionIssueSource> {
|
||||
OptionIssueSource::some(self.source)
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn parse_segment_config_from_source(
|
||||
module_asset: ModuleVc,
|
||||
) -> Result<NextSegmentConfigVc> {
|
||||
let Some(ecmascript_asset) = EcmascriptModuleAssetVc::resolve_from(module_asset).await? else {
|
||||
return Ok(NextSegmentConfigVc::default());
|
||||
module_asset: Vc<Box<dyn Module>>,
|
||||
) -> Result<Vc<NextSegmentConfig>> {
|
||||
let Some(ecmascript_asset) =
|
||||
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(module_asset).await?
|
||||
else {
|
||||
return Ok(Default::default());
|
||||
};
|
||||
|
||||
let ParseResult::Ok {
|
||||
|
@ -224,7 +224,7 @@ pub async fn parse_segment_config_from_source(
|
|||
..
|
||||
} = &*ecmascript_asset.parse().await?
|
||||
else {
|
||||
return Ok(NextSegmentConfigVc::default());
|
||||
return Ok(Default::default());
|
||||
};
|
||||
|
||||
let mut config = NextSegmentConfig::default();
|
||||
|
@ -252,12 +252,12 @@ pub async fn parse_segment_config_from_source(
|
|||
Ok(config.cell())
|
||||
}
|
||||
|
||||
fn issue_source(source: AssetVc, span: Span) -> IssueSourceVc {
|
||||
IssueSourceVc::from_byte_offset(source, span.lo.to_usize(), span.hi.to_usize())
|
||||
fn issue_source(source: Vc<Box<dyn Asset>>, span: Span) -> Vc<IssueSource> {
|
||||
IssueSource::from_byte_offset(source, span.lo.to_usize(), span.hi.to_usize())
|
||||
}
|
||||
|
||||
fn parse_config_value(
|
||||
module: ModuleVc,
|
||||
module: Vc<Box<dyn Module>>,
|
||||
config: &mut NextSegmentConfig,
|
||||
ident: &Ident,
|
||||
init: &Expr,
|
||||
|
@ -268,11 +268,10 @@ fn parse_config_value(
|
|||
let (explainer, hints) = value.explain(2, 0);
|
||||
NextSegmentConfigParsingIssue {
|
||||
ident: module.ident(),
|
||||
detail: StringVc::cell(format!("{detail} Got {explainer}.{hints}")),
|
||||
source: issue_source(module.into(), span),
|
||||
detail: Vc::cell(format!("{detail} Got {explainer}.{hints}")),
|
||||
source: issue_source(Vc::upcast(module), span),
|
||||
}
|
||||
.cell()
|
||||
.as_issue()
|
||||
.emit();
|
||||
};
|
||||
|
||||
|
@ -370,9 +369,9 @@ fn parse_config_value(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn parse_segment_config_from_loader_tree(
|
||||
loader_tree: LoaderTreeVc,
|
||||
context: AssetContextVc,
|
||||
) -> Result<NextSegmentConfigVc> {
|
||||
loader_tree: Vc<LoaderTree>,
|
||||
context: Vc<Box<dyn AssetContext>>,
|
||||
) -> Result<Vc<NextSegmentConfig>> {
|
||||
let loader_tree = loader_tree.await?;
|
||||
let components = loader_tree.components.await?;
|
||||
let mut config = NextSegmentConfig::default();
|
||||
|
@ -392,7 +391,7 @@ pub async fn parse_segment_config_from_loader_tree(
|
|||
{
|
||||
config.apply_parent_config(
|
||||
&*parse_segment_config_from_source(context.process(
|
||||
FileSourceVc::new(component).into(),
|
||||
Vc::upcast(FileSource::new(component)),
|
||||
turbo_tasks::Value::new(ReferenceType::EcmaScriptModules(
|
||||
EcmaScriptModulesReferenceSubType::Undefined,
|
||||
)),
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,4 @@
|
|||
use std::{
|
||||
borrow::Cow,
|
||||
collections::{BTreeMap, HashMap},
|
||||
};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use indexmap::{indexmap, map::Entry, IndexMap};
|
||||
|
@ -9,38 +6,36 @@ use once_cell::sync::Lazy;
|
|||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turbo_tasks::{
|
||||
debug::ValueDebugFormat,
|
||||
primitives::{StringVc, StringsVc},
|
||||
trace::TraceRawVcs,
|
||||
CompletionVc, CompletionsVc, TaskInput, ValueToString,
|
||||
debug::ValueDebugFormat, trace::TraceRawVcs, Completion, Completions, TaskInput, ValueToString,
|
||||
Vc,
|
||||
};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPathVc},
|
||||
turbopack::core::issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc},
|
||||
turbo::tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPath},
|
||||
turbopack::core::issue::{Issue, IssueExt, IssueSeverity},
|
||||
};
|
||||
|
||||
use crate::next_config::NextConfigVc;
|
||||
use crate::next_config::NextConfig;
|
||||
|
||||
/// A final route in the app directory.
|
||||
#[turbo_tasks::value]
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct Components {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub page: Option<FileSystemPathVc>,
|
||||
pub page: Option<Vc<FileSystemPath>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub layout: Option<FileSystemPathVc>,
|
||||
pub layout: Option<Vc<FileSystemPath>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub error: Option<FileSystemPathVc>,
|
||||
pub error: Option<Vc<FileSystemPath>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub loading: Option<FileSystemPathVc>,
|
||||
pub loading: Option<Vc<FileSystemPath>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub template: Option<FileSystemPathVc>,
|
||||
pub template: Option<Vc<FileSystemPath>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub not_found: Option<FileSystemPathVc>,
|
||||
pub not_found: Option<Vc<FileSystemPath>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub default: Option<FileSystemPathVc>,
|
||||
pub default: Option<Vc<FileSystemPath>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub route: Option<FileSystemPathVc>,
|
||||
pub route: Option<Vc<FileSystemPath>>,
|
||||
#[serde(skip_serializing_if = "Metadata::is_empty")]
|
||||
pub metadata: Metadata,
|
||||
}
|
||||
|
@ -76,13 +71,13 @@ impl Components {
|
|||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ComponentsVc {
|
||||
impl Components {
|
||||
/// Returns a completion that changes when any route in the components
|
||||
/// changes.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn routes_changed(self) -> Result<CompletionVc> {
|
||||
pub async fn routes_changed(self: Vc<Self>) -> Result<Vc<Completion>> {
|
||||
self.await?;
|
||||
Ok(CompletionVc::new())
|
||||
Ok(Completion::new())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,19 +85,19 @@ impl ComponentsVc {
|
|||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, TraceRawVcs)]
|
||||
pub enum MetadataWithAltItem {
|
||||
Static {
|
||||
path: FileSystemPathVc,
|
||||
alt_path: Option<FileSystemPathVc>,
|
||||
path: Vc<FileSystemPath>,
|
||||
alt_path: Option<Vc<FileSystemPath>>,
|
||||
},
|
||||
Dynamic {
|
||||
path: FileSystemPathVc,
|
||||
path: Vc<FileSystemPath>,
|
||||
},
|
||||
}
|
||||
|
||||
/// A single metadata file.
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, TraceRawVcs)]
|
||||
pub enum MetadataItem {
|
||||
Static { path: FileSystemPathVc },
|
||||
Dynamic { path: FileSystemPathVc },
|
||||
Static { path: Vc<FileSystemPath> },
|
||||
Dynamic { path: Vc<FileSystemPath> },
|
||||
}
|
||||
|
||||
/// Metadata file that can be placed in any segment of the app directory.
|
||||
|
@ -184,16 +179,16 @@ impl GlobalMetadata {
|
|||
#[derive(Debug)]
|
||||
pub struct DirectoryTree {
|
||||
/// key is e.g. "dashboard", "(dashboard)", "@slot"
|
||||
pub subdirectories: BTreeMap<String, DirectoryTreeVc>,
|
||||
pub components: ComponentsVc,
|
||||
pub subdirectories: BTreeMap<String, Vc<DirectoryTree>>,
|
||||
pub components: Vc<Components>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl DirectoryTreeVc {
|
||||
impl DirectoryTree {
|
||||
/// Returns a completion that changes when any route in the whole tree
|
||||
/// changes.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn routes_changed(self) -> Result<CompletionVc> {
|
||||
pub async fn routes_changed(self: Vc<Self>) -> Result<Vc<Completion>> {
|
||||
let DirectoryTree {
|
||||
subdirectories,
|
||||
components,
|
||||
|
@ -203,54 +198,57 @@ impl DirectoryTreeVc {
|
|||
for child in subdirectories.values() {
|
||||
children.push(child.routes_changed());
|
||||
}
|
||||
Ok(CompletionsVc::cell(children).completed())
|
||||
Ok(Vc::<Completions>::cell(children).completed())
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub struct OptionAppDir(Option<FileSystemPathVc>);
|
||||
pub struct OptionAppDir(Option<Vc<FileSystemPath>>);
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl OptionAppDirVc {
|
||||
impl OptionAppDir {
|
||||
/// Returns a completion that changes when any route in the whole tree
|
||||
/// changes.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn routes_changed(self, next_config: NextConfigVc) -> Result<CompletionVc> {
|
||||
pub async fn routes_changed(
|
||||
self: Vc<Self>,
|
||||
next_config: Vc<NextConfig>,
|
||||
) -> Result<Vc<Completion>> {
|
||||
if let Some(app_dir) = *self.await? {
|
||||
let directory_tree = get_directory_tree(app_dir, next_config.page_extensions());
|
||||
directory_tree.routes_changed().await?;
|
||||
}
|
||||
Ok(CompletionVc::new())
|
||||
Ok(Completion::new())
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds and returns the [DirectoryTree] of the app directory if existing.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn find_app_dir(project_path: FileSystemPathVc) -> Result<OptionAppDirVc> {
|
||||
let app = project_path.join("app");
|
||||
let src_app = project_path.join("src/app");
|
||||
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_dir = if *app.get_type().await? == FileSystemEntryType::Directory {
|
||||
app
|
||||
} else if *src_app.get_type().await? == FileSystemEntryType::Directory {
|
||||
src_app
|
||||
} else {
|
||||
return Ok(OptionAppDirVc::cell(None));
|
||||
return Ok(Vc::cell(None));
|
||||
}
|
||||
.resolve()
|
||||
.await?;
|
||||
|
||||
Ok(OptionAppDirVc::cell(Some(app_dir)))
|
||||
Ok(Vc::cell(Some(app_dir)))
|
||||
}
|
||||
|
||||
/// Finds and returns the [DirectoryTree] of the app directory if enabled and
|
||||
/// existing.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn find_app_dir_if_enabled(
|
||||
project_path: FileSystemPathVc,
|
||||
next_config: NextConfigVc,
|
||||
) -> Result<OptionAppDirVc> {
|
||||
project_path: Vc<FileSystemPath>,
|
||||
next_config: Vc<NextConfig>,
|
||||
) -> Result<Vc<OptionAppDir>> {
|
||||
if !*next_config.app_dir().await? {
|
||||
return Ok(OptionAppDirVc::cell(None));
|
||||
return Ok(Vc::cell(None));
|
||||
}
|
||||
Ok(find_app_dir(project_path))
|
||||
}
|
||||
|
@ -297,9 +295,9 @@ fn match_metadata_file<'a>(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
async fn get_directory_tree(
|
||||
dir: FileSystemPathVc,
|
||||
page_extensions: StringsVc,
|
||||
) -> Result<DirectoryTreeVc> {
|
||||
dir: Vc<FileSystemPath>,
|
||||
page_extensions: Vc<Vec<String>>,
|
||||
) -> Result<Vc<DirectoryTree>> {
|
||||
let DirectoryContent::Entries(entries) = &*dir.read_dir().await? else {
|
||||
bail!("{} must be a directory", dir.to_string().await?);
|
||||
};
|
||||
|
@ -367,7 +365,7 @@ async fn get_directory_tree(
|
|||
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));
|
||||
let alt_path =
|
||||
matches!(&*alt_path.get_type().await?, FileSystemEntryType::File)
|
||||
.then_some(alt_path);
|
||||
|
@ -416,16 +414,16 @@ async fn get_directory_tree(
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct LoaderTree {
|
||||
pub segment: String,
|
||||
pub parallel_routes: IndexMap<String, LoaderTreeVc>,
|
||||
pub components: ComponentsVc,
|
||||
pub parallel_routes: IndexMap<String, Vc<LoaderTree>>,
|
||||
pub components: Vc<Components>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn merge_loader_trees(
|
||||
app_dir: FileSystemPathVc,
|
||||
tree1: LoaderTreeVc,
|
||||
tree2: LoaderTreeVc,
|
||||
) -> Result<LoaderTreeVc> {
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
tree1: Vc<LoaderTree>,
|
||||
tree2: Vc<LoaderTree>,
|
||||
) -> Result<Vc<LoaderTree>> {
|
||||
let tree1 = tree1.await?;
|
||||
let tree2 = tree2.await?;
|
||||
|
||||
|
@ -463,8 +461,8 @@ async fn merge_loader_trees(
|
|||
TaskInput,
|
||||
)]
|
||||
pub enum Entrypoint {
|
||||
AppPage { loader_tree: LoaderTreeVc },
|
||||
AppRoute { path: FileSystemPathVc },
|
||||
AppPage { loader_tree: Vc<LoaderTree> },
|
||||
AppRoute { path: Vc<FileSystemPath> },
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(transparent)]
|
||||
|
@ -479,10 +477,10 @@ fn match_parallel_route(name: &str) -> Option<&str> {
|
|||
}
|
||||
|
||||
async fn add_parallel_route(
|
||||
app_dir: FileSystemPathVc,
|
||||
result: &mut IndexMap<String, LoaderTreeVc>,
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
result: &mut IndexMap<String, Vc<LoaderTree>>,
|
||||
key: String,
|
||||
loader_tree: LoaderTreeVc,
|
||||
loader_tree: Vc<LoaderTree>,
|
||||
) -> Result<()> {
|
||||
match result.entry(key) {
|
||||
Entry::Occupied(mut e) => {
|
||||
|
@ -499,10 +497,10 @@ async fn add_parallel_route(
|
|||
}
|
||||
|
||||
async fn add_app_page(
|
||||
app_dir: FileSystemPathVc,
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
result: &mut IndexMap<String, Entrypoint>,
|
||||
key: String,
|
||||
loader_tree: LoaderTreeVc,
|
||||
loader_tree: Vc<LoaderTree>,
|
||||
) -> Result<()> {
|
||||
match result.entry(key) {
|
||||
Entry::Occupied(mut e) => {
|
||||
|
@ -510,11 +508,10 @@ async fn add_app_page(
|
|||
let Entrypoint::AppPage { loader_tree: value } = value else {
|
||||
DirectoryTreeIssue {
|
||||
app_dir,
|
||||
message: StringVc::cell(format!("Conflicting route at {}", e.key())),
|
||||
message: Vc::cell(format!("Conflicting route at {}", e.key())),
|
||||
severity: IssueSeverity::Error.cell(),
|
||||
}
|
||||
.cell()
|
||||
.as_issue()
|
||||
.emit();
|
||||
return Ok(());
|
||||
};
|
||||
|
@ -530,20 +527,19 @@ async fn add_app_page(
|
|||
}
|
||||
|
||||
async fn add_app_route(
|
||||
app_dir: FileSystemPathVc,
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
result: &mut IndexMap<String, Entrypoint>,
|
||||
key: String,
|
||||
path: FileSystemPathVc,
|
||||
path: Vc<FileSystemPath>,
|
||||
) -> Result<()> {
|
||||
match result.entry(key) {
|
||||
Entry::Occupied(mut e) => {
|
||||
DirectoryTreeIssue {
|
||||
app_dir,
|
||||
message: StringVc::cell(format!("Conflicting route at {}", e.key())),
|
||||
message: Vc::cell(format!("Conflicting route at {}", e.key())),
|
||||
severity: IssueSeverity::Error.cell(),
|
||||
}
|
||||
.cell()
|
||||
.as_issue()
|
||||
.emit();
|
||||
*e.get_mut() = Entrypoint::AppRoute { path };
|
||||
}
|
||||
|
@ -555,25 +551,28 @@ async fn add_app_route(
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub fn get_entrypoints(app_dir: FileSystemPathVc, page_extensions: StringsVc) -> EntrypointsVc {
|
||||
pub fn get_entrypoints(
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
page_extensions: Vc<Vec<String>>,
|
||||
) -> Vc<Entrypoints> {
|
||||
directory_tree_to_entrypoints(app_dir, get_directory_tree(app_dir, page_extensions))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn directory_tree_to_entrypoints(
|
||||
app_dir: FileSystemPathVc,
|
||||
directory_tree: DirectoryTreeVc,
|
||||
) -> EntrypointsVc {
|
||||
directory_tree_to_entrypoints_internal(app_dir, "", directory_tree, "/")
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
directory_tree: Vc<DirectoryTree>,
|
||||
) -> Vc<Entrypoints> {
|
||||
directory_tree_to_entrypoints_internal(app_dir, "".to_string(), directory_tree, "/".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn directory_tree_to_entrypoints_internal(
|
||||
app_dir: FileSystemPathVc,
|
||||
directory_name: &str,
|
||||
directory_tree: DirectoryTreeVc,
|
||||
path_prefix: &str,
|
||||
) -> Result<EntrypointsVc> {
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
directory_name: String,
|
||||
directory_tree: Vc<DirectoryTree>,
|
||||
path_prefix: String,
|
||||
) -> Result<Vc<Entrypoints>> {
|
||||
let mut result = IndexMap::new();
|
||||
|
||||
let directory_tree = &*directory_tree.await?;
|
||||
|
@ -581,7 +580,7 @@ async fn directory_tree_to_entrypoints_internal(
|
|||
let subdirectories = &directory_tree.subdirectories;
|
||||
let components = directory_tree.components.await?;
|
||||
|
||||
let current_level_is_parallel_route = is_parallel_route(directory_name);
|
||||
let current_level_is_parallel_route = is_parallel_route(&directory_name);
|
||||
|
||||
if let Some(page) = components.page {
|
||||
add_app_page(
|
||||
|
@ -692,18 +691,17 @@ async fn directory_tree_to_entrypoints_internal(
|
|||
let parallel_route_key = match_parallel_route(subdir_name);
|
||||
let map = directory_tree_to_entrypoints_internal(
|
||||
app_dir,
|
||||
subdir_name,
|
||||
subdir_name.to_string(),
|
||||
subdirectory,
|
||||
// TODO(alexkirsz) We don't check optional segment here because Next.js seems to expect
|
||||
// it, although this might just need to be computed as "original name".
|
||||
if parallel_route_key.is_some() {
|
||||
Cow::Borrowed(path_prefix)
|
||||
path_prefix.clone()
|
||||
} else if path_prefix == "/" {
|
||||
format!("/{subdir_name}").into()
|
||||
format!("/{subdir_name}")
|
||||
} else {
|
||||
format!("{path_prefix}/{subdir_name}").into()
|
||||
}
|
||||
.as_ref(),
|
||||
format!("{path_prefix}/{subdir_name}")
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
for (full_path, &entrypoint) in map.iter() {
|
||||
|
@ -731,7 +729,7 @@ async fn directory_tree_to_entrypoints_internal(
|
|||
}
|
||||
}
|
||||
}
|
||||
Ok(EntrypointsVc::cell(result))
|
||||
Ok(Vc::cell(result))
|
||||
}
|
||||
|
||||
/// ref: https://github.com/vercel/next.js/blob/c390c1662bc79e12cf7c037dcb382ef5ead6e492/packages/next/src/build/entries.ts#L119
|
||||
|
@ -743,9 +741,9 @@ fn get_underscore_normalized_path(path: &str) -> String {
|
|||
/// Returns the global metadata for an app directory.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_global_metadata(
|
||||
app_dir: FileSystemPathVc,
|
||||
page_extensions: StringsVc,
|
||||
) -> Result<GlobalMetadataVc> {
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
page_extensions: Vc<Vec<String>>,
|
||||
) -> Result<Vc<GlobalMetadata>> {
|
||||
let DirectoryContent::Entries(entries) = &*app_dir.read_dir().await? else {
|
||||
bail!("app_dir must be a directory")
|
||||
};
|
||||
|
@ -778,37 +776,37 @@ pub async fn get_global_metadata(
|
|||
|
||||
#[turbo_tasks::value(shared)]
|
||||
struct DirectoryTreeIssue {
|
||||
pub severity: IssueSeverityVc,
|
||||
pub app_dir: FileSystemPathVc,
|
||||
pub message: StringVc,
|
||||
pub severity: Vc<IssueSeverity>,
|
||||
pub app_dir: Vc<FileSystemPath>,
|
||||
pub message: Vc<String>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Issue for DirectoryTreeIssue {
|
||||
#[turbo_tasks::function]
|
||||
fn severity(&self) -> IssueSeverityVc {
|
||||
fn severity(&self) -> Vc<IssueSeverity> {
|
||||
self.severity
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn title(&self) -> Result<StringVc> {
|
||||
Ok(StringVc::cell(
|
||||
async fn title(&self) -> Result<Vc<String>> {
|
||||
Ok(Vc::cell(
|
||||
"An issue occurred while preparing your Next.js app".to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn category(&self) -> StringVc {
|
||||
StringVc::cell("next app".to_string())
|
||||
fn category(&self) -> Vc<String> {
|
||||
Vc::cell("next app".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn context(&self) -> FileSystemPathVc {
|
||||
fn context(&self) -> Vc<FileSystemPath> {
|
||||
self.app_dir
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn description(&self) -> StringVc {
|
||||
fn description(&self) -> Vc<String> {
|
||||
self.message
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
use anyhow::Result;
|
||||
use turbo_tasks::{
|
||||
primitives::{BoolVc, StringVc},
|
||||
Value,
|
||||
};
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::{FileSystemEntryType, FileSystemPathVc},
|
||||
turbo::tasks_fs::{FileSystemEntryType, FileSystemPath},
|
||||
turbopack::{
|
||||
core::{
|
||||
issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc},
|
||||
resolve::{parse::RequestVc, pattern::Pattern, resolve},
|
||||
issue::{Issue, IssueExt, IssueSeverity},
|
||||
resolve::{parse::Request, pattern::Pattern, resolve},
|
||||
},
|
||||
node::transforms::webpack::{WebpackLoaderItem, WebpackLoaderItemsVc},
|
||||
node::transforms::webpack::WebpackLoaderItem,
|
||||
turbopack::{
|
||||
module_options::{LoaderRuleItem, OptionWebpackRulesVc, WebpackRulesVc},
|
||||
module_options::{LoaderRuleItem, OptionWebpackRules, WebpackRules},
|
||||
resolve_options,
|
||||
resolve_options_context::ResolveOptionsContext,
|
||||
},
|
||||
|
@ -36,13 +33,13 @@ const BABEL_CONFIG_FILES: &[&str] = &[
|
|||
/// webpack loader for each eligible file type if it doesn't already exist.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn maybe_add_babel_loader(
|
||||
project_root: FileSystemPathVc,
|
||||
webpack_rules: Option<WebpackRulesVc>,
|
||||
) -> Result<OptionWebpackRulesVc> {
|
||||
project_root: Vc<FileSystemPath>,
|
||||
webpack_rules: Option<Vc<WebpackRules>>,
|
||||
) -> 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).get_type().await?;
|
||||
let filetype = *project_root.join(filename.to_string()).get_type().await?;
|
||||
if matches!(filetype, FileSystemEntryType::File) {
|
||||
has_babel_config = true;
|
||||
break;
|
||||
|
@ -76,18 +73,17 @@ pub async fn maybe_add_babel_loader(
|
|||
{
|
||||
BabelIssue {
|
||||
path: project_root,
|
||||
title: StringVc::cell(
|
||||
title: Vc::cell(
|
||||
"Unable to resolve babel-loader, but a babel config is present"
|
||||
.to_owned(),
|
||||
),
|
||||
description: StringVc::cell(
|
||||
description: Vc::cell(
|
||||
"Make sure babel-loader is installed via your package manager."
|
||||
.to_owned(),
|
||||
),
|
||||
severity: IssueSeverity::Fatal.cell(),
|
||||
}
|
||||
.cell()
|
||||
.as_issue()
|
||||
.emit();
|
||||
|
||||
has_emitted_babel_resolve_issue = true;
|
||||
|
@ -100,12 +96,12 @@ pub async fn maybe_add_babel_loader(
|
|||
if let Some(rule) = rule {
|
||||
let mut loaders = rule.loaders.await?.clone_value();
|
||||
loaders.push(loader);
|
||||
rule.loaders = WebpackLoaderItemsVc::cell(loaders);
|
||||
rule.loaders = Vc::cell(loaders);
|
||||
} else {
|
||||
rules.insert(
|
||||
pattern.to_string(),
|
||||
LoaderRuleItem {
|
||||
loaders: WebpackLoaderItemsVc::cell(vec![loader]),
|
||||
loaders: Vc::cell(vec![loader]),
|
||||
rename_as: Some("*".to_string()),
|
||||
},
|
||||
);
|
||||
|
@ -115,19 +111,17 @@ pub async fn maybe_add_babel_loader(
|
|||
}
|
||||
|
||||
if has_changed {
|
||||
return Ok(OptionWebpackRulesVc::cell(Some(WebpackRulesVc::cell(
|
||||
rules,
|
||||
))));
|
||||
return Ok(Vc::cell(Some(Vc::cell(rules))));
|
||||
}
|
||||
}
|
||||
Ok(OptionWebpackRulesVc::cell(webpack_rules))
|
||||
Ok(Vc::cell(webpack_rules))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn is_babel_loader_available(project_path: FileSystemPathVc) -> Result<BoolVc> {
|
||||
pub async fn is_babel_loader_available(project_path: Vc<FileSystemPath>) -> Result<Vc<bool>> {
|
||||
let result = resolve(
|
||||
project_path,
|
||||
RequestVc::parse(Value::new(Pattern::Constant(
|
||||
Request::parse(Value::new(Pattern::Constant(
|
||||
"babel-loader/package.json".to_string(),
|
||||
))),
|
||||
resolve_options(
|
||||
|
@ -142,41 +136,41 @@ pub async fn is_babel_loader_available(project_path: FileSystemPathVc) -> Result
|
|||
),
|
||||
);
|
||||
let assets = result.primary_assets().await?;
|
||||
Ok(BoolVc::cell(!assets.is_empty()))
|
||||
Ok(Vc::cell(!assets.is_empty()))
|
||||
}
|
||||
|
||||
#[turbo_tasks::value]
|
||||
struct BabelIssue {
|
||||
path: FileSystemPathVc,
|
||||
title: StringVc,
|
||||
description: StringVc,
|
||||
severity: IssueSeverityVc,
|
||||
path: Vc<FileSystemPath>,
|
||||
title: Vc<String>,
|
||||
description: Vc<String>,
|
||||
severity: Vc<IssueSeverity>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Issue for BabelIssue {
|
||||
#[turbo_tasks::function]
|
||||
fn category(&self) -> StringVc {
|
||||
StringVc::cell("other".to_string())
|
||||
fn category(&self) -> Vc<String> {
|
||||
Vc::cell("other".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn severity(&self) -> IssueSeverityVc {
|
||||
fn severity(&self) -> Vc<IssueSeverity> {
|
||||
self.severity
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn context(&self) -> FileSystemPathVc {
|
||||
fn context(&self) -> Vc<FileSystemPath> {
|
||||
self.path
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn title(&self) -> StringVc {
|
||||
fn title(&self) -> Vc<String> {
|
||||
self.title
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn description(&self) -> StringVc {
|
||||
fn description(&self) -> Vc<String> {
|
||||
self.description
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +1,47 @@
|
|||
use anyhow::{bail, Result};
|
||||
use indexmap::{indexmap, IndexMap};
|
||||
use turbo_tasks::{Value, ValueToString};
|
||||
use turbo_tasks_fs::{File, FileSystemPathVc};
|
||||
use turbo_tasks::{Value, ValueToString, Vc};
|
||||
use turbo_tasks_fs::{File, FileSystemPath};
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
asset::{Asset, AssetVc},
|
||||
chunk::EvaluatableAssetVc,
|
||||
context::{AssetContext, AssetContextVc},
|
||||
issue::{IssueSeverity, OptionIssueSourceVc},
|
||||
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssetsVc, ReferenceType},
|
||||
resolve::parse::RequestVc,
|
||||
source::SourceVc,
|
||||
virtual_source::VirtualSourceVc,
|
||||
asset::{Asset, AssetContent},
|
||||
chunk::EvaluatableAsset,
|
||||
context::AssetContext,
|
||||
issue::{IssueSeverity, OptionIssueSource},
|
||||
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssets, ReferenceType},
|
||||
resolve::parse::Request,
|
||||
source::Source,
|
||||
virtual_source::VirtualSource,
|
||||
},
|
||||
ecmascript::{resolve::esm_resolve, utils::StringifyJs, EcmascriptModuleAssetVc},
|
||||
ecmascript::{resolve::esm_resolve, utils::StringifyJs, EcmascriptModuleAsset},
|
||||
};
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn route_bootstrap(
|
||||
asset: AssetVc,
|
||||
context: AssetContextVc,
|
||||
base_path: FileSystemPathVc,
|
||||
bootstrap_asset: SourceVc,
|
||||
config: BootstrapConfigVc,
|
||||
) -> Result<EvaluatableAssetVc> {
|
||||
let resolve_origin = if let Some(m) = EcmascriptModuleAssetVc::resolve_from(asset).await? {
|
||||
m.as_resolve_origin()
|
||||
} else {
|
||||
bail!("asset does not represent an ecmascript module");
|
||||
};
|
||||
asset: Vc<Box<dyn Asset>>,
|
||||
context: Vc<Box<dyn AssetContext>>,
|
||||
base_path: Vc<FileSystemPath>,
|
||||
bootstrap_asset: Vc<Box<dyn Source>>,
|
||||
config: Vc<BootstrapConfig>,
|
||||
) -> Result<Vc<Box<dyn EvaluatableAsset>>> {
|
||||
let resolve_origin =
|
||||
if let Some(m) = Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(asset).await? {
|
||||
Vc::upcast(m)
|
||||
} else {
|
||||
bail!("asset does not represent an ecmascript module");
|
||||
};
|
||||
|
||||
// TODO: this is where you'd switch the route kind to the one you need
|
||||
let route_module_kind = "app-route";
|
||||
|
||||
let resolved_route_module_asset = esm_resolve(
|
||||
resolve_origin,
|
||||
RequestVc::parse_string(format!(
|
||||
Request::parse_string(format!(
|
||||
"next/dist/server/future/route-modules/{}/module",
|
||||
route_module_kind
|
||||
)),
|
||||
Value::new(EcmaScriptModulesReferenceSubType::Undefined),
|
||||
OptionIssueSourceVc::none(),
|
||||
OptionIssueSource::none(),
|
||||
IssueSeverity::Error.cell(),
|
||||
);
|
||||
let route_module_asset = match &*resolved_route_module_asset.first_asset().await? {
|
||||
|
@ -53,7 +54,7 @@ pub async fn route_bootstrap(
|
|||
context,
|
||||
base_path,
|
||||
bootstrap_asset,
|
||||
InnerAssetsVc::cell(indexmap! {
|
||||
Vc::cell(indexmap! {
|
||||
"ROUTE_MODULE".to_string() => route_module_asset,
|
||||
}),
|
||||
config,
|
||||
|
@ -64,22 +65,22 @@ pub async fn route_bootstrap(
|
|||
pub struct BootstrapConfig(IndexMap<String, String>);
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl BootstrapConfigVc {
|
||||
impl BootstrapConfig {
|
||||
#[turbo_tasks::function]
|
||||
pub fn empty() -> Self {
|
||||
BootstrapConfigVc::cell(IndexMap::new())
|
||||
pub fn empty() -> Vc<Self> {
|
||||
Vc::cell(IndexMap::new())
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn bootstrap(
|
||||
asset: AssetVc,
|
||||
context: AssetContextVc,
|
||||
base_path: FileSystemPathVc,
|
||||
bootstrap_asset: SourceVc,
|
||||
inner_assets: InnerAssetsVc,
|
||||
config: BootstrapConfigVc,
|
||||
) -> Result<EvaluatableAssetVc> {
|
||||
asset: Vc<Box<dyn Asset>>,
|
||||
context: Vc<Box<dyn AssetContext>>,
|
||||
base_path: Vc<FileSystemPath>,
|
||||
bootstrap_asset: Vc<Box<dyn Source>>,
|
||||
inner_assets: Vc<InnerAssets>,
|
||||
config: Vc<BootstrapConfig>,
|
||||
) -> Result<Vc<Box<dyn EvaluatableAsset>>> {
|
||||
let path = asset.ident().path().await?;
|
||||
let Some(path) = base_path.await?.get_path_to(&path) else {
|
||||
bail!(
|
||||
|
@ -106,31 +107,32 @@ pub async fn bootstrap(
|
|||
config.insert("KIND".to_string(), "APP_ROUTE".to_string());
|
||||
|
||||
let config_asset = context.process(
|
||||
VirtualSourceVc::new(
|
||||
asset.ident().path().join("bootstrap-config.ts"),
|
||||
File::from(
|
||||
config
|
||||
.iter()
|
||||
.map(|(k, v)| format!("export const {} = {};\n", k, StringifyJs(v)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(""),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::empty())),
|
||||
Vc::upcast(VirtualSource::new(
|
||||
asset.ident().path().join("bootstrap-config.ts".to_string()),
|
||||
AssetContent::file(
|
||||
File::from(
|
||||
config
|
||||
.iter()
|
||||
.map(|(k, v)| format!("export const {} = {};\n", k, StringifyJs(v)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(""),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
)),
|
||||
Value::new(ReferenceType::Internal(InnerAssets::empty())),
|
||||
);
|
||||
|
||||
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.into());
|
||||
inner_assets.insert("BOOTSTRAP_CONFIG".to_string(), Vc::upcast(config_asset));
|
||||
|
||||
let asset = context.process(
|
||||
bootstrap_asset,
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(inner_assets))),
|
||||
Value::new(ReferenceType::Internal(Vc::cell(inner_assets))),
|
||||
);
|
||||
|
||||
let Some(asset) = EvaluatableAssetVc::resolve_from(asset).await? else {
|
||||
let Some(asset) = Vc::try_resolve_sidecast::<Box<dyn EvaluatableAsset>>(asset).await? else {
|
||||
bail!("internal module must be evaluatable");
|
||||
};
|
||||
|
||||
|
|
|
@ -1,27 +1,28 @@
|
|||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::{FileContentVc, FileSystem, FileSystemPathVc, FileSystemVc},
|
||||
turbopack::core::{file_source::FileSourceVc, source::SourceVc},
|
||||
turbo::tasks_fs::{FileContent, FileSystem, FileSystemPath},
|
||||
turbopack::core::{file_source::FileSource, source::Source},
|
||||
};
|
||||
|
||||
pub const VIRTUAL_PACKAGE_NAME: &str = "@vercel/turbopack-next";
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(crate) fn next_js_fs() -> FileSystemVc {
|
||||
pub(crate) fn next_js_fs() -> Vc<Box<dyn FileSystem>> {
|
||||
// [TODO]: macro need to be refactored to be used via turbopack-binding
|
||||
turbo_tasks_fs::embed_directory!("next", "$CARGO_MANIFEST_DIR/js/src")
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(crate) fn next_js_file(path: &str) -> FileContentVc {
|
||||
pub(crate) fn next_js_file(path: String) -> Vc<FileContent> {
|
||||
next_js_fs().root().join(path).read()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(crate) fn next_js_file_path(path: &str) -> FileSystemPathVc {
|
||||
pub(crate) fn next_js_file_path(path: String) -> Vc<FileSystemPath> {
|
||||
next_js_fs().root().join(path)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(crate) fn next_asset(path: &str) -> SourceVc {
|
||||
FileSourceVc::new(next_js_file_path(path)).into()
|
||||
pub(crate) fn next_asset(path: String) -> Vc<Box<dyn Source>> {
|
||||
Vc::upcast(FileSource::new(next_js_file_path(path)))
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use anyhow::Result;
|
||||
use turbo_tasks::{
|
||||
graph::{AdjacencyMap, GraphTraversal},
|
||||
CompletionVc, CompletionsVc, TryJoinIterExt,
|
||||
Completion, Completions, TryJoinIterExt, Vc,
|
||||
};
|
||||
use turbo_tasks_fs::{rebase, FileSystemPathVc};
|
||||
use turbo_tasks_fs::{rebase, FileSystemPath};
|
||||
use turbopack_binding::turbopack::core::{
|
||||
asset::Asset,
|
||||
output::{OutputAssetVc, OutputAssetsVc},
|
||||
output::{OutputAsset, OutputAssets},
|
||||
reference::AssetReference,
|
||||
};
|
||||
|
||||
|
@ -14,31 +14,36 @@ use turbopack_binding::turbopack::core::{
|
|||
/// inside the node root or the client root.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn emit_all_assets(
|
||||
assets: OutputAssetsVc,
|
||||
node_root: FileSystemPathVc,
|
||||
client_relative_path: FileSystemPathVc,
|
||||
client_output_path: FileSystemPathVc,
|
||||
) -> Result<CompletionVc> {
|
||||
assets: Vc<OutputAssets>,
|
||||
node_root: Vc<FileSystemPath>,
|
||||
client_relative_path: Vc<FileSystemPath>,
|
||||
client_output_path: Vc<FileSystemPath>,
|
||||
) -> Result<Vc<Completion>> {
|
||||
let all_assets = all_assets_from_entries(assets).await?;
|
||||
Ok(CompletionsVc::all(
|
||||
Ok(Completions::all(
|
||||
all_assets
|
||||
.iter()
|
||||
.copied()
|
||||
.map(|asset| async move {
|
||||
if asset.ident().path().await?.is_inside(&*node_root.await?) {
|
||||
if asset
|
||||
.ident()
|
||||
.path()
|
||||
.await?
|
||||
.is_inside_ref(&*node_root.await?)
|
||||
{
|
||||
return Ok(emit(asset));
|
||||
} else if asset
|
||||
.ident()
|
||||
.path()
|
||||
.await?
|
||||
.is_inside(&*client_relative_path.await?)
|
||||
.is_inside_ref(&*client_relative_path.await?)
|
||||
{
|
||||
// Client assets are emitted to the client output path, which is prefixed with
|
||||
// _next. We need to rebase them to remove that prefix.
|
||||
return Ok(emit_rebase(asset, client_relative_path, client_output_path));
|
||||
}
|
||||
|
||||
Ok(CompletionVc::immutable())
|
||||
Ok(Completion::immutable())
|
||||
})
|
||||
.try_join()
|
||||
.await?,
|
||||
|
@ -46,12 +51,16 @@ pub async fn emit_all_assets(
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn emit(asset: OutputAssetVc) -> CompletionVc {
|
||||
fn emit(asset: Vc<Box<dyn OutputAsset>>) -> Vc<Completion> {
|
||||
asset.content().write(asset.ident().path())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn emit_rebase(asset: OutputAssetVc, from: FileSystemPathVc, to: FileSystemPathVc) -> CompletionVc {
|
||||
fn emit_rebase(
|
||||
asset: Vc<Box<dyn OutputAsset>>,
|
||||
from: Vc<FileSystemPath>,
|
||||
to: Vc<FileSystemPath>,
|
||||
) -> Vc<Completion> {
|
||||
asset
|
||||
.content()
|
||||
.write(rebase(asset.ident().path(), from, to))
|
||||
|
@ -60,8 +69,8 @@ fn emit_rebase(asset: OutputAssetVc, from: FileSystemPathVc, to: FileSystemPathV
|
|||
/// Walks the asset graph from multiple assets and collect all referenced
|
||||
/// assets.
|
||||
#[turbo_tasks::function]
|
||||
async fn all_assets_from_entries(entries: OutputAssetsVc) -> Result<OutputAssetsVc> {
|
||||
Ok(OutputAssetsVc::cell(
|
||||
async fn all_assets_from_entries(entries: Vc<OutputAssets>) -> Result<Vc<OutputAssets>> {
|
||||
Ok(Vc::cell(
|
||||
AdjacencyMap::new()
|
||||
.skip_duplicates()
|
||||
.visit(entries.await?.iter().copied(), get_referenced_assets)
|
||||
|
@ -75,23 +84,27 @@ async fn all_assets_from_entries(entries: OutputAssetsVc) -> Result<OutputAssets
|
|||
|
||||
/// Computes the list of all chunk children of a given chunk.
|
||||
async fn get_referenced_assets(
|
||||
asset: OutputAssetVc,
|
||||
) -> Result<impl Iterator<Item = OutputAssetVc> + Send> {
|
||||
Ok(asset
|
||||
.references()
|
||||
.await?
|
||||
.iter()
|
||||
.map(|reference| async move {
|
||||
let primary_assets = reference.resolve_reference().primary_assets().await?;
|
||||
Ok(primary_assets.clone_value())
|
||||
})
|
||||
.try_join()
|
||||
.await?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|asset| async move { Ok(OutputAssetVc::resolve_from(asset).await?) })
|
||||
.try_join()
|
||||
.await?
|
||||
.into_iter()
|
||||
.flatten())
|
||||
asset: Vc<Box<dyn OutputAsset>>,
|
||||
) -> Result<impl Iterator<Item = Vc<Box<dyn OutputAsset>>> + Send> {
|
||||
Ok(
|
||||
asset
|
||||
.references()
|
||||
.await?
|
||||
.iter()
|
||||
.map(|reference| async move {
|
||||
let primary_assets = reference.resolve_reference().primary_assets().await?;
|
||||
Ok(primary_assets.clone_value())
|
||||
})
|
||||
.try_join()
|
||||
.await?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|asset| async move {
|
||||
Ok(Vc::try_resolve_sidecast::<Box<dyn OutputAsset>>(asset).await?)
|
||||
})
|
||||
.try_join()
|
||||
.await?
|
||||
.into_iter()
|
||||
.flatten(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
use anyhow::Result;
|
||||
use indexmap::indexmap;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_env::{
|
||||
CustomProcessEnvVc, EnvMapVc, FilterProcessEnvVc, ProcessEnv, ProcessEnvVc,
|
||||
},
|
||||
turbopack::env::EmbeddableProcessEnvVc,
|
||||
turbo::tasks_env::{CustomProcessEnv, EnvMap, FilterProcessEnv, ProcessEnv},
|
||||
turbopack::env::EmbeddableProcessEnv,
|
||||
};
|
||||
|
||||
use crate::next_config::NextConfigVc;
|
||||
use crate::next_config::NextConfig;
|
||||
|
||||
/// Creates a ProcessEnvVc safe to use in JS, by stringifying and encoding as
|
||||
/// regular JS strings. Setting `client` to true will additionally filter the
|
||||
/// env to just the keys that are acceptable for the client to access.
|
||||
/// Creates a Vc<Box<dyn ProcessEnv>> safe to use in JS, by stringifying and
|
||||
/// encoding as regular JS strings. Setting `client` to true will additionally
|
||||
/// filter the env to just the keys that are acceptable for the client to
|
||||
/// access.
|
||||
///
|
||||
/// For now, it also injects overridden values as if they were real JS code, eg
|
||||
/// an Object and not a String.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn env_for_js(
|
||||
env: ProcessEnvVc,
|
||||
env: Vc<Box<dyn ProcessEnv>>,
|
||||
client: bool,
|
||||
next_config: NextConfigVc,
|
||||
) -> Result<ProcessEnvVc> {
|
||||
let test_mode = env.read("__NEXT_TEST_MODE").await?;
|
||||
next_config: Vc<NextConfig>,
|
||||
) -> Result<Vc<Box<dyn ProcessEnv>>> {
|
||||
let test_mode = env.read("__NEXT_TEST_MODE".to_string()).await?;
|
||||
let test_mode = test_mode.as_deref().unwrap_or("");
|
||||
|
||||
let env = if client {
|
||||
FilterProcessEnvVc::new(
|
||||
Vc::upcast(FilterProcessEnv::new(
|
||||
env,
|
||||
vec![
|
||||
"NEXT_PUBLIC_".to_string(),
|
||||
"NODE_ENV".to_string(),
|
||||
"PORT".to_string(),
|
||||
],
|
||||
)
|
||||
.into()
|
||||
))
|
||||
} else {
|
||||
// Server doesn't need to have env vars injected since it will have them in the
|
||||
// real process.env.
|
||||
EnvMapVc::cell(Default::default()).into()
|
||||
Vc::upcast(EnvMap::empty())
|
||||
};
|
||||
|
||||
let env =
|
||||
EmbeddableProcessEnvVc::new(CustomProcessEnvVc::new(env, next_config.env()).into()).into();
|
||||
let env = Vc::upcast(EmbeddableProcessEnv::new(Vc::upcast(
|
||||
CustomProcessEnv::new(env, next_config.env()),
|
||||
)));
|
||||
|
||||
let image_config = next_config.image_config().await?;
|
||||
let mut map = indexmap! {
|
||||
|
@ -65,5 +65,5 @@ pub async fn env_for_js(
|
|||
map.insert("__NEXT_TEST_MODE".to_string(), "true".to_string());
|
||||
}
|
||||
|
||||
Ok(CustomProcessEnvVc::new(env, EnvMapVc::cell(map)).into())
|
||||
Ok(Vc::upcast(CustomProcessEnv::new(env, Vc::cell(map))))
|
||||
}
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::Value;
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::{tasks_env::ProcessEnvVc, tasks_fs::FileSystemPathVc},
|
||||
turbo::{tasks_env::ProcessEnv, tasks_fs::FileSystemPath},
|
||||
turbopack::{
|
||||
core::{
|
||||
compile_time_info::CompileTimeInfoVc,
|
||||
context::AssetContextVc,
|
||||
resolve::{options::ImportMap, origin::PlainResolveOriginVc},
|
||||
},
|
||||
dev_server::html::DevHtmlAssetVc,
|
||||
node::execution_context::ExecutionContextVc,
|
||||
turbopack::{
|
||||
ecmascript::EcmascriptModuleAssetVc, transition::TransitionsByNameVc,
|
||||
ModuleAssetContextVc,
|
||||
compile_time_info::CompileTimeInfo,
|
||||
context::AssetContext,
|
||||
resolve::{options::ImportMap, origin::PlainResolveOrigin},
|
||||
},
|
||||
dev_server::html::DevHtmlAsset,
|
||||
node::execution_context::ExecutionContext,
|
||||
turbopack::{ecmascript::EcmascriptModuleAsset, ModuleAssetContext},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -25,20 +22,20 @@ use crate::{
|
|||
get_client_chunking_context, get_client_module_options_context,
|
||||
get_client_resolve_options_context, get_client_runtime_entries, ClientContextType,
|
||||
},
|
||||
next_config::NextConfigVc,
|
||||
next_config::NextConfig,
|
||||
next_import_map::insert_next_shared_aliases,
|
||||
runtime::resolve_runtime_request,
|
||||
};
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_fallback_page(
|
||||
project_path: FileSystemPathVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
dev_server_root: FileSystemPathVc,
|
||||
env: ProcessEnvVc,
|
||||
client_compile_time_info: CompileTimeInfoVc,
|
||||
next_config: NextConfigVc,
|
||||
) -> Result<DevHtmlAssetVc> {
|
||||
project_path: Vc<FileSystemPath>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
dev_server_root: Vc<FileSystemPath>,
|
||||
env: Vc<Box<dyn ProcessEnv>>,
|
||||
client_compile_time_info: Vc<CompileTimeInfo>,
|
||||
next_config: Vc<NextConfig>,
|
||||
) -> Result<Vc<DevHtmlAsset>> {
|
||||
let ty = Value::new(ClientContextType::Fallback);
|
||||
let mode = NextMode::Development;
|
||||
let resolve_options_context =
|
||||
|
@ -69,35 +66,34 @@ pub async fn get_fallback_page(
|
|||
)
|
||||
.await?;
|
||||
|
||||
let context: AssetContextVc = ModuleAssetContextVc::new(
|
||||
TransitionsByNameVc::cell(HashMap::new()),
|
||||
let context: Vc<Box<dyn AssetContext>> = Vc::upcast(ModuleAssetContext::new(
|
||||
Vc::cell(HashMap::new()),
|
||||
client_compile_time_info,
|
||||
module_options_context,
|
||||
resolve_options_context.with_extended_import_map(import_map.cell()),
|
||||
)
|
||||
.into();
|
||||
));
|
||||
|
||||
let runtime_entries = entries.resolve_entries(context);
|
||||
|
||||
let fallback_chunk = resolve_runtime_request(
|
||||
PlainResolveOriginVc::new(context, project_path).into(),
|
||||
"entry/fallback",
|
||||
Vc::upcast(PlainResolveOrigin::new(context, project_path)),
|
||||
"entry/fallback".to_string(),
|
||||
);
|
||||
|
||||
let module = if let Some(module) =
|
||||
EcmascriptModuleAssetVc::resolve_from(fallback_chunk.as_asset()).await?
|
||||
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(fallback_chunk).await?
|
||||
{
|
||||
module
|
||||
} else {
|
||||
bail!("fallback runtime entry is not an ecmascript module");
|
||||
};
|
||||
|
||||
Ok(DevHtmlAssetVc::new(
|
||||
dev_server_root.join("fallback.html"),
|
||||
Ok(DevHtmlAsset::new(
|
||||
dev_server_root.join("fallback.html".to_string()),
|
||||
vec![(
|
||||
module.into(),
|
||||
chunking_context.into(),
|
||||
Some(runtime_entries.with_entry(module.into())),
|
||||
Vc::upcast(module),
|
||||
Vc::upcast(chunking_context),
|
||||
Some(runtime_entries.with_entry(Vc::upcast(module))),
|
||||
)],
|
||||
))
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#![feature(async_closure)]
|
||||
#![feature(str_split_remainder)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(async_fn_in_trait)]
|
||||
|
||||
mod app_render;
|
||||
mod app_segment_config;
|
||||
|
@ -47,9 +49,7 @@ mod web_entry_source;
|
|||
|
||||
pub use app_source::create_app_source;
|
||||
pub use emit::emit_all_assets;
|
||||
pub use next_app::unsupported_dynamic_metadata_issue::{
|
||||
UnsupportedDynamicMetadataIssue, UnsupportedDynamicMetadataIssueVc,
|
||||
};
|
||||
pub use next_app::unsupported_dynamic_metadata_issue::UnsupportedDynamicMetadataIssue;
|
||||
pub use page_loader::create_page_loader_entry_module;
|
||||
pub use page_source::create_page_source;
|
||||
pub use turbopack_binding::{turbopack::node::source_map, *};
|
||||
|
|
|
@ -2,46 +2,41 @@ use anyhow::Result;
|
|||
use async_recursion::async_recursion;
|
||||
use indexmap::IndexMap;
|
||||
use indoc::formatdoc;
|
||||
use turbo_tasks::{Value, ValueToString};
|
||||
use turbo_tasks_fs::FileSystemPathVc;
|
||||
use turbo_tasks::{Value, ValueToString, Vc};
|
||||
use turbo_tasks_fs::FileSystemPath;
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
asset::AssetVc,
|
||||
asset::Asset,
|
||||
context::AssetContext,
|
||||
file_source::FileSourceVc,
|
||||
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssetsVc, ReferenceType},
|
||||
},
|
||||
ecmascript::{magic_identifier, text::TextContentFileSourceVc, utils::StringifyJs},
|
||||
r#static::StaticModuleAssetVc,
|
||||
turbopack::{
|
||||
transition::{Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
file_source::FileSource,
|
||||
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssets, ReferenceType},
|
||||
},
|
||||
ecmascript::{magic_identifier, text::TextContentFileSource, utils::StringifyJs},
|
||||
r#static::StaticModuleAsset,
|
||||
turbopack::{transition::Transition, ModuleAssetContext},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app_structure::{
|
||||
Components, LoaderTree, LoaderTreeVc, Metadata, MetadataItem, MetadataWithAltItem,
|
||||
},
|
||||
app_structure::{Components, LoaderTree, Metadata, MetadataItem, MetadataWithAltItem},
|
||||
mode::NextMode,
|
||||
next_image::module::{BlurPlaceholderMode, StructuredImageModuleType},
|
||||
};
|
||||
|
||||
pub struct LoaderTreeBuilder {
|
||||
inner_assets: IndexMap<String, AssetVc>,
|
||||
inner_assets: IndexMap<String, Vc<Box<dyn Asset>>>,
|
||||
counter: usize,
|
||||
imports: Vec<String>,
|
||||
loader_tree_code: String,
|
||||
context: ModuleAssetContextVc,
|
||||
unsupported_metadata: Vec<FileSystemPathVc>,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
unsupported_metadata: Vec<Vc<FileSystemPath>>,
|
||||
mode: NextMode,
|
||||
server_component_transition: ServerComponentTransition,
|
||||
pages: Vec<FileSystemPathVc>,
|
||||
pages: Vec<Vc<FileSystemPath>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ServerComponentTransition {
|
||||
Transition(TransitionVc),
|
||||
Transition(Vc<Box<dyn Transition>>),
|
||||
TransitionName(String),
|
||||
}
|
||||
|
||||
|
@ -72,7 +67,7 @@ impl ComponentType {
|
|||
|
||||
impl LoaderTreeBuilder {
|
||||
fn new(
|
||||
context: ModuleAssetContextVc,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
server_component_transition: ServerComponentTransition,
|
||||
mode: NextMode,
|
||||
) -> Self {
|
||||
|
@ -98,7 +93,7 @@ impl LoaderTreeBuilder {
|
|||
async fn write_component(
|
||||
&mut self,
|
||||
ty: ComponentType,
|
||||
component: Option<FileSystemPathVc>,
|
||||
component: Option<Vc<FileSystemPath>>,
|
||||
) -> Result<()> {
|
||||
use std::fmt::Write;
|
||||
|
||||
|
@ -149,7 +144,7 @@ impl LoaderTreeBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
let source = FileSourceVc::new(component).into();
|
||||
let source = Vc::upcast(FileSource::new(component));
|
||||
let reference_ty = Value::new(ReferenceType::EcmaScriptModules(
|
||||
EcmaScriptModulesReferenceSubType::Undefined,
|
||||
));
|
||||
|
@ -160,12 +155,12 @@ impl LoaderTreeBuilder {
|
|||
}
|
||||
ServerComponentTransition::TransitionName(transition_name) => self
|
||||
.context
|
||||
.with_transition(transition_name.as_str())
|
||||
.with_transition(transition_name.clone())
|
||||
.process(source, reference_ty),
|
||||
};
|
||||
|
||||
self.inner_assets
|
||||
.insert(format!("COMPONENT_{i}"), module.into());
|
||||
.insert(format!("COMPONENT_{i}"), Vc::upcast(module));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -206,8 +201,10 @@ impl LoaderTreeBuilder {
|
|||
.push(format!("import {identifier} from \"{inner_module_id}\";"));
|
||||
self.inner_assets.insert(
|
||||
inner_module_id,
|
||||
StaticModuleAssetVc::new(FileSourceVc::new(path).into(), self.context.into())
|
||||
.into(),
|
||||
Vc::upcast(StaticModuleAsset::new(
|
||||
Vc::upcast(FileSource::new(path)),
|
||||
Vc::upcast(self.context),
|
||||
)),
|
||||
);
|
||||
writeln!(self.loader_tree_code, " manifest: {identifier},")?;
|
||||
}
|
||||
|
@ -249,12 +246,11 @@ impl LoaderTreeBuilder {
|
|||
MetadataWithAltItem::Static { path, alt_path } => {
|
||||
self.inner_assets.insert(
|
||||
inner_module_id,
|
||||
StructuredImageModuleType::create_module(
|
||||
FileSourceVc::new(*path).into(),
|
||||
Vc::upcast(StructuredImageModuleType::create_module(
|
||||
Vc::upcast(FileSource::new(*path)),
|
||||
BlurPlaceholderMode::None,
|
||||
self.context,
|
||||
)
|
||||
.into(),
|
||||
)),
|
||||
);
|
||||
writeln!(self.loader_tree_code, "{s}(async (props) => [{{")?;
|
||||
writeln!(self.loader_tree_code, "{s} url: {identifier}.src,")?;
|
||||
|
@ -275,13 +271,12 @@ impl LoaderTreeBuilder {
|
|||
.push(format!("import {identifier} from \"{inner_module_id}\";"));
|
||||
self.inner_assets.insert(
|
||||
inner_module_id,
|
||||
self.context
|
||||
.process(
|
||||
TextContentFileSourceVc::new(FileSourceVc::new(*alt_path).into())
|
||||
.into(),
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::empty())),
|
||||
)
|
||||
.into(),
|
||||
Vc::upcast(self.context.process(
|
||||
Vc::upcast(TextContentFileSource::new(Vc::upcast(FileSource::new(
|
||||
*alt_path,
|
||||
)))),
|
||||
Value::new(ReferenceType::Internal(InnerAssets::empty())),
|
||||
)),
|
||||
);
|
||||
writeln!(self.loader_tree_code, "{s} alt: {identifier},")?;
|
||||
}
|
||||
|
@ -295,7 +290,7 @@ impl LoaderTreeBuilder {
|
|||
}
|
||||
|
||||
#[async_recursion]
|
||||
async fn walk_tree(&mut self, loader_tree: LoaderTreeVc) -> Result<()> {
|
||||
async fn walk_tree(&mut self, loader_tree: Vc<LoaderTree>) -> Result<()> {
|
||||
use std::fmt::Write;
|
||||
|
||||
let LoaderTree {
|
||||
|
@ -344,7 +339,7 @@ impl LoaderTreeBuilder {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn build(mut self, loader_tree: LoaderTreeVc) -> Result<LoaderTreeModule> {
|
||||
async fn build(mut self, loader_tree: Vc<LoaderTree>) -> Result<LoaderTreeModule> {
|
||||
self.walk_tree(loader_tree).await?;
|
||||
Ok(LoaderTreeModule {
|
||||
imports: self.imports,
|
||||
|
@ -359,15 +354,15 @@ impl LoaderTreeBuilder {
|
|||
pub struct LoaderTreeModule {
|
||||
pub imports: Vec<String>,
|
||||
pub loader_tree_code: String,
|
||||
pub inner_assets: IndexMap<String, AssetVc>,
|
||||
pub unsupported_metadata: Vec<FileSystemPathVc>,
|
||||
pub pages: Vec<FileSystemPathVc>,
|
||||
pub inner_assets: IndexMap<String, Vc<Box<dyn Asset>>>,
|
||||
pub unsupported_metadata: Vec<Vc<FileSystemPath>>,
|
||||
pub pages: Vec<Vc<FileSystemPath>>,
|
||||
}
|
||||
|
||||
impl LoaderTreeModule {
|
||||
pub async fn build(
|
||||
loader_tree: LoaderTreeVc,
|
||||
context: ModuleAssetContextVc,
|
||||
loader_tree: Vc<LoaderTree>,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
server_component_transition: ServerComponentTransition,
|
||||
mode: NextMode,
|
||||
) -> Result<Self> {
|
||||
|
|
|
@ -4,57 +4,51 @@ use mime::{APPLICATION_JAVASCRIPT_UTF_8, APPLICATION_JSON};
|
|||
use serde::Serialize;
|
||||
use turbo_tasks::{
|
||||
graph::{GraphTraversal, NonDeterministic},
|
||||
primitives::{StringReadRef, StringVc, StringsVc},
|
||||
ReadRef, Vc,
|
||||
};
|
||||
use turbopack_binding::{
|
||||
turbo::{tasks::TryJoinIterExt, tasks_fs::File},
|
||||
turbopack::{
|
||||
core::{
|
||||
asset::AssetContentVc,
|
||||
introspect::{Introspectable, IntrospectableVc},
|
||||
},
|
||||
core::{asset::AssetContent, introspect::Introspectable, version::VersionedContentExt},
|
||||
dev_server::source::{
|
||||
route_tree::{BaseSegment, RouteTreeVc, RouteTreesVc, RouteType},
|
||||
ContentSource, ContentSourceContentVc, ContentSourceData, ContentSourceVc,
|
||||
GetContentSourceContent, GetContentSourceContentVc,
|
||||
route_tree::{BaseSegment, RouteTree, RouteTrees, RouteType},
|
||||
ContentSource, ContentSourceContent, ContentSourceData, GetContentSourceContent,
|
||||
},
|
||||
node::render::{
|
||||
node_api_source::NodeApiContentSourceVc, rendered_source::NodeRenderContentSourceVc,
|
||||
node_api_source::NodeApiContentSource, rendered_source::NodeRenderContentSource,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
embed_js::next_js_file,
|
||||
next_config::{RewritesReadRef, RewritesVc},
|
||||
util::get_asset_path_from_pathname,
|
||||
};
|
||||
use crate::{embed_js::next_js_file, next_config::Rewrites, util::get_asset_path_from_pathname};
|
||||
|
||||
/// A content source which creates the next.js `_devPagesManifest.json` and
|
||||
/// `_devMiddlewareManifest.json` which are used for client side navigation.
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct DevManifestContentSource {
|
||||
pub page_roots: Vec<ContentSourceVc>,
|
||||
pub rewrites: RewritesVc,
|
||||
pub page_roots: Vec<Vc<Box<dyn ContentSource>>>,
|
||||
pub rewrites: Vc<Rewrites>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl DevManifestContentSourceVc {
|
||||
impl DevManifestContentSource {
|
||||
/// Recursively find all routes in the `page_roots` content sources.
|
||||
#[turbo_tasks::function]
|
||||
async fn find_routes(self) -> Result<StringsVc> {
|
||||
async fn find_routes(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
|
||||
let this = &*self.await?;
|
||||
|
||||
async fn content_source_to_pathname(
|
||||
content_source: ContentSourceVc,
|
||||
) -> Result<Option<StringReadRef>> {
|
||||
content_source: Vc<Box<dyn ContentSource>>,
|
||||
) -> Result<Option<ReadRef<String>>> {
|
||||
// TODO This shouldn't use casts but an public api instead
|
||||
if let Some(api_source) = NodeApiContentSourceVc::resolve_from(content_source).await? {
|
||||
if let Some(api_source) =
|
||||
Vc::try_resolve_downcast_type::<NodeApiContentSource>(content_source).await?
|
||||
{
|
||||
return Ok(Some(api_source.get_pathname().await?));
|
||||
}
|
||||
|
||||
if let Some(page_source) =
|
||||
NodeRenderContentSourceVc::resolve_from(content_source).await?
|
||||
Vc::try_resolve_downcast_type::<NodeRenderContentSource>(content_source).await?
|
||||
{
|
||||
return Ok(Some(page_source.get_pathname().await?));
|
||||
}
|
||||
|
@ -63,8 +57,8 @@ impl DevManifestContentSourceVc {
|
|||
}
|
||||
|
||||
async fn get_content_source_children(
|
||||
content_source: ContentSourceVc,
|
||||
) -> Result<Vec<ContentSourceVc>> {
|
||||
content_source: Vc<Box<dyn ContentSource>>,
|
||||
) -> Result<Vec<Vc<Box<dyn ContentSource>>>> {
|
||||
Ok(content_source.get_children().await?.clone_value())
|
||||
}
|
||||
|
||||
|
@ -85,13 +79,13 @@ impl DevManifestContentSourceVc {
|
|||
routes.sort_by_cached_key(|s| s.split('/').map(PageSortKey::from).collect::<Vec<_>>());
|
||||
routes.dedup();
|
||||
|
||||
Ok(StringsVc::cell(routes))
|
||||
Ok(Vc::cell(routes))
|
||||
}
|
||||
|
||||
/// Recursively find all pages in the `page_roots` content sources
|
||||
/// (excluding api routes).
|
||||
#[turbo_tasks::function]
|
||||
async fn find_pages(self) -> Result<StringsVc> {
|
||||
async fn find_pages(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
|
||||
let routes = &*self.find_routes().await?;
|
||||
|
||||
// we don't need to sort as it's already sorted by `find_routes`
|
||||
|
@ -101,12 +95,12 @@ impl DevManifestContentSourceVc {
|
|||
.cloned()
|
||||
.collect();
|
||||
|
||||
Ok(StringsVc::cell(pages))
|
||||
Ok(Vc::cell(pages))
|
||||
}
|
||||
|
||||
/// Create a build manifest with all pages.
|
||||
#[turbo_tasks::function]
|
||||
async fn create_build_manifest(self) -> Result<StringVc> {
|
||||
async fn create_build_manifest(self: Vc<Self>) -> Result<Vc<String>> {
|
||||
let this = &*self.await?;
|
||||
|
||||
let sorted_pages = &*self.find_pages().await?;
|
||||
|
@ -129,7 +123,7 @@ impl DevManifestContentSourceVc {
|
|||
routes,
|
||||
};
|
||||
|
||||
let manifest = next_js_file("entry/manifest/buildManifest.js")
|
||||
let manifest = next_js_file("entry/manifest/buildManifest.js".to_string())
|
||||
.await?
|
||||
.as_content()
|
||||
.context("embedded buildManifest file missing")?
|
||||
|
@ -137,7 +131,7 @@ impl DevManifestContentSourceVc {
|
|||
.to_str()?
|
||||
.replace("$$MANIFEST$$", &serde_json::to_string(&manifest)?);
|
||||
|
||||
Ok(StringVc::cell(manifest))
|
||||
Ok(Vc::cell(manifest))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,7 +139,7 @@ impl DevManifestContentSourceVc {
|
|||
#[serde(rename_all = "camelCase")]
|
||||
struct BuildManifest<'a> {
|
||||
#[serde(rename = "__rewrites")]
|
||||
rewrites: RewritesReadRef,
|
||||
rewrites: ReadRef<Rewrites>,
|
||||
sorted_pages: &'a Vec<String>,
|
||||
|
||||
#[serde(flatten)]
|
||||
|
@ -160,22 +154,22 @@ const DEV_MIDDLEWARE_MANIFEST_PATHNAME: &str =
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ContentSource for DevManifestContentSource {
|
||||
#[turbo_tasks::function]
|
||||
fn get_routes(self_vc: DevManifestContentSourceVc) -> RouteTreeVc {
|
||||
RouteTreesVc::cell(vec![
|
||||
RouteTreeVc::new_route(
|
||||
fn get_routes(self: Vc<Self>) -> Vc<RouteTree> {
|
||||
Vc::<RouteTrees>::cell(vec![
|
||||
RouteTree::new_route(
|
||||
BaseSegment::from_static_pathname(DEV_MANIFEST_PATHNAME).collect(),
|
||||
RouteType::Exact,
|
||||
self_vc.into(),
|
||||
Vc::upcast(self),
|
||||
),
|
||||
RouteTreeVc::new_route(
|
||||
RouteTree::new_route(
|
||||
BaseSegment::from_static_pathname(BUILD_MANIFEST_PATHNAME).collect(),
|
||||
RouteType::Exact,
|
||||
self_vc.into(),
|
||||
Vc::upcast(self),
|
||||
),
|
||||
RouteTreeVc::new_route(
|
||||
RouteTree::new_route(
|
||||
BaseSegment::from_static_pathname(DEV_MIDDLEWARE_MANIFEST_PATHNAME).collect(),
|
||||
RouteType::Exact,
|
||||
self_vc.into(),
|
||||
Vc::upcast(self),
|
||||
),
|
||||
])
|
||||
.merge()
|
||||
|
@ -186,13 +180,13 @@ impl ContentSource for DevManifestContentSource {
|
|||
impl GetContentSourceContent for DevManifestContentSource {
|
||||
#[turbo_tasks::function]
|
||||
async fn get(
|
||||
self_vc: DevManifestContentSourceVc,
|
||||
path: &str,
|
||||
self: Vc<Self>,
|
||||
path: String,
|
||||
_data: turbo_tasks::Value<ContentSourceData>,
|
||||
) -> Result<ContentSourceContentVc> {
|
||||
let manifest_file = match path {
|
||||
) -> Result<Vc<ContentSourceContent>> {
|
||||
let manifest_file = match path.as_str() {
|
||||
DEV_MANIFEST_PATHNAME => {
|
||||
let pages = &*self_vc.find_routes().await?;
|
||||
let pages = &*self.find_routes().await?;
|
||||
|
||||
File::from(serde_json::to_string(&serde_json::json!({
|
||||
"pages": pages,
|
||||
|
@ -200,7 +194,7 @@ impl GetContentSourceContent for DevManifestContentSource {
|
|||
.with_content_type(APPLICATION_JSON)
|
||||
}
|
||||
BUILD_MANIFEST_PATHNAME => {
|
||||
let build_manifest = &*self_vc.create_build_manifest().await?;
|
||||
let build_manifest = &*self.create_build_manifest().await?;
|
||||
|
||||
File::from(build_manifest.as_str()).with_content_type(APPLICATION_JAVASCRIPT_UTF_8)
|
||||
}
|
||||
|
@ -215,8 +209,8 @@ impl GetContentSourceContent for DevManifestContentSource {
|
|||
_ => bail!("unknown path: {}", path),
|
||||
};
|
||||
|
||||
Ok(ContentSourceContentVc::static_content(
|
||||
AssetContentVc::from(manifest_file).into(),
|
||||
Ok(ContentSourceContent::static_content(
|
||||
AssetContent::file(manifest_file.into()).versioned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -224,13 +218,13 @@ impl GetContentSourceContent for DevManifestContentSource {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Introspectable for DevManifestContentSource {
|
||||
#[turbo_tasks::function]
|
||||
fn ty(&self) -> StringVc {
|
||||
StringVc::cell("dev manifest source".to_string())
|
||||
fn ty(&self) -> Vc<String> {
|
||||
Vc::cell("dev manifest source".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn details(&self) -> StringVc {
|
||||
StringVc::cell(
|
||||
fn details(&self) -> Vc<String> {
|
||||
Vc::cell(
|
||||
"provides _devPagesManifest.json, _buildManifest.js and _devMiddlewareManifest.json."
|
||||
.to_string(),
|
||||
)
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
use anyhow::Result;
|
||||
use turbo_tasks::{primitives::StringVc, TryJoinIterExt, ValueToString};
|
||||
use turbo_tasks_fs::FileSystemPathVc;
|
||||
use turbo_tasks::{TryJoinIterExt, ValueToString, Vc};
|
||||
use turbo_tasks_fs::FileSystemPath;
|
||||
use turbopack_binding::turbopack::{
|
||||
core::issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc},
|
||||
core::issue::{Issue, IssueSeverity},
|
||||
ecmascript::utils::FormatIter,
|
||||
};
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct UnsupportedDynamicMetadataIssue {
|
||||
pub app_dir: FileSystemPathVc,
|
||||
pub files: Vec<FileSystemPathVc>,
|
||||
pub app_dir: Vc<FileSystemPath>,
|
||||
pub files: Vec<Vc<FileSystemPath>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Issue for UnsupportedDynamicMetadataIssue {
|
||||
#[turbo_tasks::function]
|
||||
fn severity(&self) -> IssueSeverityVc {
|
||||
fn severity(&self) -> Vc<IssueSeverity> {
|
||||
IssueSeverity::Warning.into()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn category(&self) -> StringVc {
|
||||
StringVc::cell("unsupported".to_string())
|
||||
fn category(&self) -> Vc<String> {
|
||||
Vc::cell("unsupported".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn context(&self) -> FileSystemPathVc {
|
||||
fn context(&self) -> Vc<FileSystemPath> {
|
||||
self.app_dir
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn title(&self) -> StringVc {
|
||||
StringVc::cell(
|
||||
fn title(&self) -> Vc<String> {
|
||||
Vc::cell(
|
||||
"Dynamic metadata from filesystem is currently not supported in Turbopack".to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn description(&self) -> Result<StringVc> {
|
||||
async fn description(&self) -> Result<Vc<String>> {
|
||||
let mut files = self
|
||||
.files
|
||||
.iter()
|
||||
|
@ -45,7 +45,7 @@ impl Issue for UnsupportedDynamicMetadataIssue {
|
|||
.try_join()
|
||||
.await?;
|
||||
files.sort();
|
||||
Ok(StringVc::cell(format!(
|
||||
Ok(Vc::cell(format!(
|
||||
"The following files were found in the app directory, but are not supported by \
|
||||
Turbopack. They are ignored:\n{}",
|
||||
FormatIter(|| files.iter().flat_map(|file| vec!["\n- ", file]))
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
use anyhow::Result;
|
||||
use turbo_tasks::primitives::StringVc;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::FileSystemPathVc,
|
||||
turbopack::core::resolve::options::{ImportMapping, ImportMappingVc},
|
||||
turbo::tasks_fs::FileSystemPath, turbopack::core::resolve::options::ImportMapping,
|
||||
};
|
||||
|
||||
use crate::next_import_map::get_next_package;
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_postcss_package_mapping(
|
||||
project_path: FileSystemPathVc,
|
||||
) -> Result<ImportMappingVc> {
|
||||
project_path: Vc<FileSystemPath>,
|
||||
) -> 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(),
|
||||
|
@ -25,8 +24,8 @@ pub async fn get_postcss_package_mapping(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_external_next_compiled_package_mapping(
|
||||
package_name: StringVc,
|
||||
) -> Result<ImportMappingVc> {
|
||||
package_name: Vc<String>,
|
||||
) -> Result<Vc<ImportMapping>> {
|
||||
Ok(
|
||||
ImportMapping::Alternatives(vec![ImportMapping::External(Some(format!(
|
||||
"next/dist/compiled/{}",
|
||||
|
|
|
@ -1,38 +1,33 @@
|
|||
use core::{default::Default, result::Result::Ok};
|
||||
|
||||
use anyhow::Result;
|
||||
use turbo_tasks::{
|
||||
primitives::{OptionStringVc, StringVc},
|
||||
Value,
|
||||
};
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbo_tasks_fs::FileSystem;
|
||||
use turbopack_binding::{
|
||||
turbo::{tasks_env::ProcessEnvVc, tasks_fs::FileSystemPathVc},
|
||||
turbo::{tasks_env::ProcessEnv, tasks_fs::FileSystemPath},
|
||||
turbopack::{
|
||||
core::{
|
||||
compile_time_defines,
|
||||
compile_time_info::{
|
||||
CompileTimeDefines, CompileTimeDefinesVc, CompileTimeInfo, CompileTimeInfoVc,
|
||||
FreeVarReference, FreeVarReferencesVc,
|
||||
CompileTimeDefines, CompileTimeInfo, FreeVarReference, FreeVarReferences,
|
||||
},
|
||||
environment::{BrowserEnvironment, EnvironmentVc, ExecutionEnvironment},
|
||||
environment::{BrowserEnvironment, Environment, ExecutionEnvironment},
|
||||
free_var_references,
|
||||
resolve::{parse::RequestVc, pattern::Pattern},
|
||||
resolve::{parse::Request, pattern::Pattern},
|
||||
},
|
||||
dev::{react_refresh::assert_can_resolve_react_refresh, DevChunkingContextVc},
|
||||
ecmascript::{chunk::EcmascriptChunkingContextVc, TransformPluginVc},
|
||||
dev::{react_refresh::assert_can_resolve_react_refresh, DevChunkingContext},
|
||||
ecmascript::chunk::EcmascriptChunkingContext,
|
||||
ecmascript_plugin::transform::directives::server::ServerDirectiveTransformer,
|
||||
env::ProcessEnvAssetVc,
|
||||
node::execution_context::ExecutionContextVc,
|
||||
env::ProcessEnvAsset,
|
||||
node::execution_context::ExecutionContext,
|
||||
turbopack::{
|
||||
condition::ContextCondition,
|
||||
module_options::{
|
||||
module_options_context::{ModuleOptionsContext, ModuleOptionsContextVc},
|
||||
CustomEcmascriptTransformPlugins, CustomEcmascriptTransformPluginsVc,
|
||||
module_options_context::ModuleOptionsContext, CustomEcmascriptTransformPlugins,
|
||||
JsxTransformOptions, MdxTransformModuleOptions, PostCssTransformOptions,
|
||||
TypescriptTransformOptions, WebpackLoadersOptions,
|
||||
},
|
||||
resolve_options_context::{ResolveOptionsContext, ResolveOptionsContextVc},
|
||||
resolve_options_context::ResolveOptionsContext,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -44,14 +39,14 @@ use crate::{
|
|||
env::env_for_js,
|
||||
mode::NextMode,
|
||||
next_build::{get_external_next_compiled_package_mapping, get_postcss_package_mapping},
|
||||
next_client::runtime_entry::{RuntimeEntriesVc, RuntimeEntry},
|
||||
next_config::NextConfigVc,
|
||||
next_client::runtime_entry::{RuntimeEntries, RuntimeEntry},
|
||||
next_config::NextConfig,
|
||||
next_import_map::{
|
||||
get_next_client_fallback_import_map, get_next_client_import_map,
|
||||
get_next_client_resolved_map, mdx_import_source_file,
|
||||
},
|
||||
next_shared::{
|
||||
resolve::UnsupportedModulesResolvePluginVc,
|
||||
resolve::UnsupportedModulesResolvePlugin,
|
||||
transforms::{
|
||||
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
|
||||
styled_components::get_styled_components_transform_plugin,
|
||||
|
@ -80,12 +75,12 @@ fn defines(mode: NextMode) -> CompileTimeDefines {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn next_client_defines(mode: NextMode) -> CompileTimeDefinesVc {
|
||||
fn next_client_defines(mode: NextMode) -> Vc<CompileTimeDefines> {
|
||||
defines(mode).cell()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn next_client_free_vars(mode: NextMode) -> Result<FreeVarReferencesVc> {
|
||||
async fn next_client_free_vars(mode: NextMode) -> Result<Vc<FreeVarReferences>> {
|
||||
Ok(free_var_references!(
|
||||
..defines(mode).into_iter(),
|
||||
Buffer = FreeVarReference::EcmaScriptModule {
|
||||
|
@ -103,18 +98,19 @@ async fn next_client_free_vars(mode: NextMode) -> Result<FreeVarReferencesVc> {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub fn get_client_compile_time_info(mode: NextMode, browserslist_query: &str) -> CompileTimeInfoVc {
|
||||
CompileTimeInfo::builder(EnvironmentVc::new(Value::new(
|
||||
ExecutionEnvironment::Browser(
|
||||
BrowserEnvironment {
|
||||
dom: true,
|
||||
web_worker: false,
|
||||
service_worker: false,
|
||||
browserslist_query: browserslist_query.to_owned(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
)))
|
||||
pub fn get_client_compile_time_info(
|
||||
mode: NextMode,
|
||||
browserslist_query: String,
|
||||
) -> Vc<CompileTimeInfo> {
|
||||
CompileTimeInfo::builder(Environment::new(Value::new(ExecutionEnvironment::Browser(
|
||||
BrowserEnvironment {
|
||||
dom: true,
|
||||
web_worker: false,
|
||||
service_worker: false,
|
||||
browserslist_query: browserslist_query.to_owned(),
|
||||
}
|
||||
.into(),
|
||||
))))
|
||||
.defines(next_client_defines(mode))
|
||||
.free_var_references(next_client_free_vars(mode))
|
||||
.cell()
|
||||
|
@ -123,20 +119,20 @@ pub fn get_client_compile_time_info(mode: NextMode, browserslist_query: &str) ->
|
|||
#[turbo_tasks::value(serialization = "auto_for_input")]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord)]
|
||||
pub enum ClientContextType {
|
||||
Pages { pages_dir: FileSystemPathVc },
|
||||
App { app_dir: FileSystemPathVc },
|
||||
Pages { pages_dir: Vc<FileSystemPath> },
|
||||
App { app_dir: Vc<FileSystemPath> },
|
||||
Fallback,
|
||||
Other,
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_client_resolve_options_context(
|
||||
project_path: FileSystemPathVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
ty: Value<ClientContextType>,
|
||||
mode: NextMode,
|
||||
next_config: NextConfigVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
) -> Result<ResolveOptionsContextVc> {
|
||||
next_config: Vc<NextConfig>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
) -> Result<Vc<ResolveOptionsContext>> {
|
||||
let next_client_import_map =
|
||||
get_next_client_import_map(project_path, ty, next_config, execution_context);
|
||||
let next_client_fallback_import_map = get_next_client_fallback_import_map(ty);
|
||||
|
@ -149,7 +145,9 @@ pub async fn get_client_resolve_options_context(
|
|||
resolved_map: Some(next_client_resolved_map),
|
||||
browser: true,
|
||||
module: true,
|
||||
plugins: vec![UnsupportedModulesResolvePluginVc::new(project_path).into()],
|
||||
plugins: vec![Vc::upcast(UnsupportedModulesResolvePlugin::new(
|
||||
project_path,
|
||||
))],
|
||||
..Default::default()
|
||||
};
|
||||
Ok(ResolveOptionsContext {
|
||||
|
@ -166,13 +164,13 @@ pub async fn get_client_resolve_options_context(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_client_module_options_context(
|
||||
project_path: FileSystemPathVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
env: EnvironmentVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
env: Vc<Environment>,
|
||||
ty: Value<ClientContextType>,
|
||||
mode: NextMode,
|
||||
next_config: NextConfigVc,
|
||||
) -> Result<ModuleOptionsContextVc> {
|
||||
next_config: Vc<NextConfig>,
|
||||
) -> Result<Vc<ModuleOptionsContext>> {
|
||||
let custom_rules = get_next_client_transforms_rules(next_config, ty.into_value(), mode).await?;
|
||||
let resolve_options_context =
|
||||
get_client_resolve_options_context(project_path, ty, mode, next_config, execution_context);
|
||||
|
@ -197,9 +195,9 @@ pub async fn get_client_module_options_context(
|
|||
let enable_webpack_loaders = webpack_rules.map(|rules| {
|
||||
WebpackLoadersOptions {
|
||||
rules,
|
||||
loader_runner_package: Some(get_external_next_compiled_package_mapping(
|
||||
StringVc::cell("loader-runner".to_owned()),
|
||||
)),
|
||||
loader_runner_package: Some(get_external_next_compiled_package_mapping(Vc::cell(
|
||||
"loader-runner".to_owned(),
|
||||
))),
|
||||
}
|
||||
.cell()
|
||||
});
|
||||
|
@ -210,19 +208,17 @@ pub async fn get_client_module_options_context(
|
|||
*get_emotion_transform_plugin(next_config).await?,
|
||||
*get_styled_components_transform_plugin(next_config).await?,
|
||||
*get_styled_jsx_transform_plugin().await?,
|
||||
Some(TransformPluginVc::cell(Box::new(
|
||||
ServerDirectiveTransformer::new(
|
||||
// ServerDirective is not implemented yet and always reports an issue.
|
||||
// We don't have to pass a valid transition name yet, but the API is prepared.
|
||||
&StringVc::cell("TODO".to_string()),
|
||||
),
|
||||
))),
|
||||
Some(Vc::cell(Box::new(ServerDirectiveTransformer::new(
|
||||
// ServerDirective is not implemented yet and always reports an issue.
|
||||
// We don't have to pass a valid transition name yet, but the API is prepared.
|
||||
&Vc::cell("TODO".to_string()),
|
||||
)) as _)),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||
CustomEcmascriptTransformPlugins {
|
||||
source_transforms,
|
||||
output_transforms: vec![],
|
||||
|
@ -280,43 +276,41 @@ pub async fn get_client_module_options_context(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub fn get_client_chunking_context(
|
||||
project_path: FileSystemPathVc,
|
||||
client_root: FileSystemPathVc,
|
||||
environment: EnvironmentVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
client_root: Vc<FileSystemPath>,
|
||||
environment: Vc<Environment>,
|
||||
mode: NextMode,
|
||||
) -> EcmascriptChunkingContextVc {
|
||||
let builder = DevChunkingContextVc::builder(
|
||||
) -> Vc<Box<dyn EcmascriptChunkingContext>> {
|
||||
let builder = DevChunkingContext::builder(
|
||||
project_path,
|
||||
client_root,
|
||||
client_root.join("_next/static/chunks"),
|
||||
client_root.join("_next/static/chunks".to_string()),
|
||||
get_client_assets_path(client_root),
|
||||
environment,
|
||||
);
|
||||
|
||||
let builder = match mode {
|
||||
NextMode::Development => builder.hot_module_replacement(),
|
||||
NextMode::Build => {
|
||||
builder.chunk_base_path(OptionStringVc::cell(Some("_next/".to_string())))
|
||||
}
|
||||
NextMode::Build => builder.chunk_base_path(Vc::cell(Some("_next/".to_string()))),
|
||||
};
|
||||
|
||||
builder.build().into()
|
||||
Vc::upcast(builder.build())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub fn get_client_assets_path(client_root: FileSystemPathVc) -> FileSystemPathVc {
|
||||
client_root.join("_next/static/media")
|
||||
pub fn get_client_assets_path(client_root: Vc<FileSystemPath>) -> Vc<FileSystemPath> {
|
||||
client_root.join("_next/static/media".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_client_runtime_entries(
|
||||
project_root: FileSystemPathVc,
|
||||
env: ProcessEnvVc,
|
||||
project_root: Vc<FileSystemPath>,
|
||||
env: Vc<Box<dyn ProcessEnv>>,
|
||||
ty: Value<ClientContextType>,
|
||||
mode: NextMode,
|
||||
next_config: NextConfigVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
) -> Result<RuntimeEntriesVc> {
|
||||
next_config: Vc<NextConfig>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
) -> Result<Vc<RuntimeEntries>> {
|
||||
let mut runtime_entries = vec![];
|
||||
|
||||
if matches!(
|
||||
|
@ -324,9 +318,10 @@ pub async fn get_client_runtime_entries(
|
|||
ClientContextType::App { .. } | ClientContextType::Pages { .. },
|
||||
) {
|
||||
runtime_entries.push(
|
||||
RuntimeEntry::Source(
|
||||
ProcessEnvAssetVc::new(project_root, env_for_js(env, true, next_config)).into(),
|
||||
)
|
||||
RuntimeEntry::Source(Vc::upcast(ProcessEnvAsset::new(
|
||||
project_root,
|
||||
env_for_js(env, true, next_config),
|
||||
)))
|
||||
.cell(),
|
||||
);
|
||||
}
|
||||
|
@ -349,17 +344,18 @@ pub async fn get_client_runtime_entries(
|
|||
// because the bootstrap contains JSX which requires Refresh's global
|
||||
// functions to be available.
|
||||
if let Some(request) = enable_react_refresh {
|
||||
runtime_entries.push(RuntimeEntry::Request(request, project_root.join("_")).cell())
|
||||
runtime_entries
|
||||
.push(RuntimeEntry::Request(request, project_root.join("_".to_string())).cell())
|
||||
};
|
||||
}
|
||||
NextMode::Build => match *ty {
|
||||
ClientContextType::App { .. } => {
|
||||
runtime_entries.push(
|
||||
RuntimeEntry::Request(
|
||||
RequestVc::parse(Value::new(Pattern::Constant(
|
||||
Request::parse(Value::new(Pattern::Constant(
|
||||
"./build/client/app-bootstrap.ts".to_string(),
|
||||
))),
|
||||
next_js_fs().root().join("_"),
|
||||
next_js_fs().root().join("_".to_string()),
|
||||
)
|
||||
.cell(),
|
||||
);
|
||||
|
@ -367,10 +363,10 @@ pub async fn get_client_runtime_entries(
|
|||
ClientContextType::Pages { .. } => {
|
||||
runtime_entries.push(
|
||||
RuntimeEntry::Request(
|
||||
RequestVc::parse(Value::new(Pattern::Constant(
|
||||
Request::parse(Value::new(Pattern::Constant(
|
||||
"./build/client/bootstrap.ts".to_string(),
|
||||
))),
|
||||
next_js_fs().root().join("_"),
|
||||
next_js_fs().root().join("_".to_string()),
|
||||
)
|
||||
.cell(),
|
||||
);
|
||||
|
@ -379,5 +375,5 @@ pub async fn get_client_runtime_entries(
|
|||
},
|
||||
}
|
||||
|
||||
Ok(RuntimeEntriesVc::cell(runtime_entries))
|
||||
Ok(Vc::cell(runtime_entries))
|
||||
}
|
||||
|
|
|
@ -7,5 +7,5 @@ pub use context::{
|
|||
get_client_chunking_context, get_client_compile_time_info, get_client_module_options_context,
|
||||
get_client_resolve_options_context, get_client_runtime_entries, ClientContextType,
|
||||
};
|
||||
pub use runtime_entry::{RuntimeEntries, RuntimeEntriesVc, RuntimeEntry, RuntimeEntryVc};
|
||||
pub use runtime_entry::{RuntimeEntries, RuntimeEntry};
|
||||
pub use transition::NextClientTransition;
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::{tasks::ValueToString, tasks_fs::FileSystemPathVc},
|
||||
turbo::{tasks::ValueToString, tasks_fs::FileSystemPath},
|
||||
turbopack::{
|
||||
core::{
|
||||
asset::Asset,
|
||||
chunk::{EvaluatableAssetVc, EvaluatableAssetsVc},
|
||||
context::AssetContextVc,
|
||||
issue::{IssueSeverity, OptionIssueSourceVc},
|
||||
resolve::{origin::PlainResolveOriginVc, parse::RequestVc},
|
||||
source::SourceVc,
|
||||
chunk::{EvaluatableAsset, EvaluatableAssetExt, EvaluatableAssets},
|
||||
context::AssetContext,
|
||||
issue::{IssueSeverity, OptionIssueSource},
|
||||
resolve::{origin::PlainResolveOrigin, parse::Request},
|
||||
source::Source,
|
||||
},
|
||||
ecmascript::resolve::cjs_resolve,
|
||||
},
|
||||
|
@ -16,29 +17,30 @@ use turbopack_binding::{
|
|||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub enum RuntimeEntry {
|
||||
Request(RequestVc, FileSystemPathVc),
|
||||
Evaluatable(EvaluatableAssetVc),
|
||||
Source(SourceVc),
|
||||
Request(Vc<Request>, Vc<FileSystemPath>),
|
||||
Evaluatable(Vc<Box<dyn EvaluatableAsset>>),
|
||||
Source(Vc<Box<dyn Source>>),
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl RuntimeEntryVc {
|
||||
impl RuntimeEntry {
|
||||
#[turbo_tasks::function]
|
||||
pub async fn resolve_entry(self, context: AssetContextVc) -> Result<EvaluatableAssetsVc> {
|
||||
pub async fn resolve_entry(
|
||||
self: Vc<Self>,
|
||||
context: Vc<Box<dyn AssetContext>>,
|
||||
) -> Result<Vc<EvaluatableAssets>> {
|
||||
let (request, path) = match *self.await? {
|
||||
RuntimeEntry::Evaluatable(e) => return Ok(EvaluatableAssetsVc::one(e)),
|
||||
RuntimeEntry::Evaluatable(e) => return Ok(EvaluatableAssets::one(e)),
|
||||
RuntimeEntry::Source(source) => {
|
||||
return Ok(EvaluatableAssetsVc::one(EvaluatableAssetVc::from_source(
|
||||
source, context,
|
||||
)));
|
||||
return Ok(EvaluatableAssets::one(source.to_evaluatable(context)));
|
||||
}
|
||||
RuntimeEntry::Request(r, path) => (r, path),
|
||||
};
|
||||
|
||||
let assets = cjs_resolve(
|
||||
PlainResolveOriginVc::new(context, path).into(),
|
||||
Vc::upcast(PlainResolveOrigin::new(context, path)),
|
||||
request,
|
||||
OptionIssueSourceVc::none(),
|
||||
OptionIssueSource::none(),
|
||||
IssueSeverity::Error.cell(),
|
||||
)
|
||||
.primary_assets()
|
||||
|
@ -46,7 +48,9 @@ impl RuntimeEntryVc {
|
|||
|
||||
let mut runtime_entries = Vec::with_capacity(assets.len());
|
||||
for asset in &assets {
|
||||
if let Some(entry) = EvaluatableAssetVc::resolve_from(asset).await? {
|
||||
if let Some(entry) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn EvaluatableAsset>>(*asset).await?
|
||||
{
|
||||
runtime_entries.push(entry);
|
||||
} else {
|
||||
bail!(
|
||||
|
@ -56,17 +60,20 @@ impl RuntimeEntryVc {
|
|||
}
|
||||
}
|
||||
|
||||
Ok(EvaluatableAssetsVc::cell(runtime_entries))
|
||||
Ok(Vc::cell(runtime_entries))
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub struct RuntimeEntries(Vec<RuntimeEntryVc>);
|
||||
pub struct RuntimeEntries(Vec<Vc<RuntimeEntry>>);
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl RuntimeEntriesVc {
|
||||
impl RuntimeEntries {
|
||||
#[turbo_tasks::function]
|
||||
pub async fn resolve_entries(self, context: AssetContextVc) -> Result<EvaluatableAssetsVc> {
|
||||
pub async fn resolve_entries(
|
||||
self: Vc<Self>,
|
||||
context: Vc<Box<dyn AssetContext>>,
|
||||
) -> Result<Vc<EvaluatableAssets>> {
|
||||
let mut runtime_entries = Vec::new();
|
||||
|
||||
for reference in &self.await? {
|
||||
|
@ -74,6 +81,6 @@ impl RuntimeEntriesVc {
|
|||
runtime_entries.extend(&resolved_entries);
|
||||
}
|
||||
|
||||
Ok(EvaluatableAssetsVc::cell(runtime_entries))
|
||||
Ok(Vc::cell(runtime_entries))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use anyhow::Result;
|
||||
use next_transform_strip_page_exports::ExportFilter;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::turbopack::module_options::ModuleRule;
|
||||
|
||||
use crate::{
|
||||
mode::NextMode,
|
||||
next_client::context::ClientContextType,
|
||||
next_config::NextConfigVc,
|
||||
next_config::NextConfig,
|
||||
next_shared::transforms::{
|
||||
get_next_dynamic_transform_rule, get_next_font_transform_rule, get_next_image_rule,
|
||||
get_next_modularize_imports_rule, get_next_pages_transforms_rule,
|
||||
|
@ -15,7 +16,7 @@ use crate::{
|
|||
/// Returns a list of module rules which apply client-side, Next.js-specific
|
||||
/// transforms.
|
||||
pub async fn get_next_client_transforms_rules(
|
||||
next_config: NextConfigVc,
|
||||
next_config: Vc<NextConfig>,
|
||||
context_ty: ClientContextType,
|
||||
mode: NextMode,
|
||||
) -> Result<Vec<ModuleRule>> {
|
||||
|
|
|
@ -1,25 +1,20 @@
|
|||
use anyhow::{bail, Result};
|
||||
use indexmap::indexmap;
|
||||
use turbo_tasks::Value;
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
chunk::{ChunkingContext, ChunkingContextVc},
|
||||
compile_time_info::CompileTimeInfoVc,
|
||||
context::AssetContext,
|
||||
module::ModuleVc,
|
||||
reference_type::{InnerAssetsVc, ReferenceType},
|
||||
chunk::ChunkingContext, compile_time_info::CompileTimeInfo, context::AssetContext,
|
||||
module::Module, reference_type::ReferenceType,
|
||||
},
|
||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
||||
ecmascript::chunk::EcmascriptChunkPlaceable,
|
||||
turbopack::{
|
||||
ecmascript::chunk_group_files_asset::ChunkGroupFilesAsset,
|
||||
module_options::ModuleOptionsContextVc,
|
||||
resolve_options_context::ResolveOptionsContextVc,
|
||||
transition::{Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
module_options::ModuleOptionsContext, resolve_options_context::ResolveOptionsContext,
|
||||
transition::Transition, ModuleAssetContext,
|
||||
},
|
||||
};
|
||||
|
||||
use super::runtime_entry::RuntimeEntriesVc;
|
||||
use super::runtime_entry::RuntimeEntries;
|
||||
use crate::embed_js::next_asset;
|
||||
|
||||
/// Makes a transition into a next.js client context.
|
||||
|
@ -30,11 +25,11 @@ use crate::embed_js::next_asset;
|
|||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextClientTransition {
|
||||
pub is_app: bool,
|
||||
pub client_compile_time_info: CompileTimeInfoVc,
|
||||
pub client_module_options_context: ModuleOptionsContextVc,
|
||||
pub client_resolve_options_context: ResolveOptionsContextVc,
|
||||
pub client_chunking_context: ChunkingContextVc,
|
||||
pub runtime_entries: RuntimeEntriesVc,
|
||||
pub client_compile_time_info: Vc<CompileTimeInfo>,
|
||||
pub client_module_options_context: Vc<ModuleOptionsContext>,
|
||||
pub client_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||
pub client_chunking_context: Vc<Box<dyn ChunkingContext>>,
|
||||
pub runtime_entries: Vc<RuntimeEntries>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
|
@ -42,60 +37,65 @@ impl Transition for NextClientTransition {
|
|||
#[turbo_tasks::function]
|
||||
fn process_compile_time_info(
|
||||
&self,
|
||||
_compile_time_info: CompileTimeInfoVc,
|
||||
) -> CompileTimeInfoVc {
|
||||
_compile_time_info: Vc<CompileTimeInfo>,
|
||||
) -> Vc<CompileTimeInfo> {
|
||||
self.client_compile_time_info
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_module_options_context(
|
||||
&self,
|
||||
_context: ModuleOptionsContextVc,
|
||||
) -> ModuleOptionsContextVc {
|
||||
_context: Vc<ModuleOptionsContext>,
|
||||
) -> Vc<ModuleOptionsContext> {
|
||||
self.client_module_options_context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_resolve_options_context(
|
||||
&self,
|
||||
_context: ResolveOptionsContextVc,
|
||||
) -> ResolveOptionsContextVc {
|
||||
_context: Vc<ResolveOptionsContext>,
|
||||
) -> Vc<ResolveOptionsContext> {
|
||||
self.client_resolve_options_context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn process_module(
|
||||
&self,
|
||||
asset: ModuleVc,
|
||||
context: ModuleAssetContextVc,
|
||||
) -> Result<ModuleVc> {
|
||||
asset: Vc<Box<dyn Module>>,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
) -> Result<Vc<Box<dyn Module>>> {
|
||||
let asset = if !self.is_app {
|
||||
let internal_asset = next_asset("entry/next-hydrate.tsx");
|
||||
let internal_asset = next_asset("entry/next-hydrate.tsx".to_string());
|
||||
|
||||
context.process(
|
||||
internal_asset,
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap! {
|
||||
"PAGE".to_string() => asset.into()
|
||||
Value::new(ReferenceType::Internal(Vc::cell(indexmap! {
|
||||
"PAGE".to_string() => Vc::upcast(asset)
|
||||
}))),
|
||||
)
|
||||
} else {
|
||||
asset
|
||||
};
|
||||
let Some(asset) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? else {
|
||||
let Some(asset) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(asset).await?
|
||||
else {
|
||||
bail!("not an ecmascript placeable module");
|
||||
};
|
||||
|
||||
let runtime_entries = self.runtime_entries.resolve_entries(context.into());
|
||||
let runtime_entries = self.runtime_entries.resolve_entries(Vc::upcast(context));
|
||||
|
||||
let asset = ChunkGroupFilesAsset {
|
||||
module: asset.into(),
|
||||
module: Vc::upcast(asset),
|
||||
// This ensures that the chunk group files asset will strip out the _next prefix from
|
||||
// all chunk paths, which is what the Next.js renderer code expects.
|
||||
client_root: self.client_chunking_context.output_root().join("_next"),
|
||||
client_root: self
|
||||
.client_chunking_context
|
||||
.output_root()
|
||||
.join("_next".to_string()),
|
||||
chunking_context: self.client_chunking_context,
|
||||
runtime_entries: Some(runtime_entries),
|
||||
};
|
||||
|
||||
Ok(asset.cell().into())
|
||||
Ok(Vc::upcast(asset.cell()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,50 +1,48 @@
|
|||
use anyhow::Result;
|
||||
use turbo_tasks::Value;
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::FileSystemPathVc,
|
||||
turbo::tasks_fs::FileSystemPath,
|
||||
turbopack::{
|
||||
core::{compile_time_info::CompileTimeInfoVc, module::ModuleVc},
|
||||
ecmascript::chunk::EcmascriptChunkingContextVc,
|
||||
node::execution_context::ExecutionContextVc,
|
||||
core::{compile_time_info::CompileTimeInfo, module::Module},
|
||||
ecmascript::chunk::EcmascriptChunkingContext,
|
||||
node::execution_context::ExecutionContext,
|
||||
turbopack::{
|
||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
||||
module_options::ModuleOptionsContextVc,
|
||||
resolve_options_context::ResolveOptionsContextVc,
|
||||
transition::{Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
ecmascript::chunk::EcmascriptChunkPlaceable, module_options::ModuleOptionsContext,
|
||||
resolve_options_context::ResolveOptionsContext, transition::Transition,
|
||||
ModuleAssetContext,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
use super::with_chunks::WithChunksAssetVc;
|
||||
use super::with_chunks::WithChunksAsset;
|
||||
use crate::{
|
||||
mode::NextMode,
|
||||
next_client::context::{
|
||||
get_client_module_options_context, get_client_resolve_options_context, ClientContextType,
|
||||
},
|
||||
next_config::NextConfigVc,
|
||||
next_config::NextConfig,
|
||||
};
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextClientChunksTransition {
|
||||
pub client_compile_time_info: CompileTimeInfoVc,
|
||||
pub client_module_options_context: ModuleOptionsContextVc,
|
||||
pub client_resolve_options_context: ResolveOptionsContextVc,
|
||||
pub client_chunking_context: EcmascriptChunkingContextVc,
|
||||
pub client_compile_time_info: Vc<CompileTimeInfo>,
|
||||
pub client_module_options_context: Vc<ModuleOptionsContext>,
|
||||
pub client_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||
pub client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextClientChunksTransitionVc {
|
||||
impl NextClientChunksTransition {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(
|
||||
project_path: FileSystemPathVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
ty: Value<ClientContextType>,
|
||||
mode: NextMode,
|
||||
client_chunking_context: EcmascriptChunkingContextVc,
|
||||
client_compile_time_info: CompileTimeInfoVc,
|
||||
next_config: NextConfigVc,
|
||||
) -> NextClientChunksTransitionVc {
|
||||
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
client_compile_time_info: Vc<CompileTimeInfo>,
|
||||
next_config: Vc<NextConfig>,
|
||||
) -> Vc<NextClientChunksTransition> {
|
||||
let client_module_options_context = get_client_module_options_context(
|
||||
project_path,
|
||||
execution_context,
|
||||
|
@ -74,36 +72,41 @@ impl Transition for NextClientChunksTransition {
|
|||
#[turbo_tasks::function]
|
||||
fn process_compile_time_info(
|
||||
&self,
|
||||
_compile_time_info: CompileTimeInfoVc,
|
||||
) -> CompileTimeInfoVc {
|
||||
_compile_time_info: Vc<CompileTimeInfo>,
|
||||
) -> Vc<CompileTimeInfo> {
|
||||
self.client_compile_time_info
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_module_options_context(
|
||||
&self,
|
||||
_context: ModuleOptionsContextVc,
|
||||
) -> ModuleOptionsContextVc {
|
||||
_context: Vc<ModuleOptionsContext>,
|
||||
) -> Vc<ModuleOptionsContext> {
|
||||
self.client_module_options_context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_resolve_options_context(
|
||||
&self,
|
||||
_context: ResolveOptionsContextVc,
|
||||
) -> ResolveOptionsContextVc {
|
||||
_context: Vc<ResolveOptionsContext>,
|
||||
) -> Vc<ResolveOptionsContext> {
|
||||
self.client_resolve_options_context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn process_module(
|
||||
&self,
|
||||
asset: ModuleVc,
|
||||
_context: ModuleAssetContextVc,
|
||||
) -> Result<ModuleVc> {
|
||||
asset: Vc<Box<dyn Module>>,
|
||||
_context: Vc<ModuleAssetContext>,
|
||||
) -> Result<Vc<Box<dyn Module>>> {
|
||||
Ok(
|
||||
if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? {
|
||||
WithChunksAssetVc::new(placeable, self.client_chunking_context).into()
|
||||
if let Some(placeable) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(asset).await?
|
||||
{
|
||||
Vc::upcast(WithChunksAsset::new(
|
||||
placeable,
|
||||
self.client_chunking_context,
|
||||
))
|
||||
} else {
|
||||
asset
|
||||
},
|
||||
|
|
|
@ -1,48 +1,44 @@
|
|||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::{primitives::StringVc, Value};
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
asset::{Asset, AssetContentVc, AssetVc},
|
||||
chunk::{
|
||||
availability_info::AvailabilityInfo, ChunkVc, ChunkableModule, ChunkableModuleVc,
|
||||
ChunkingContextVc,
|
||||
},
|
||||
ident::AssetIdentVc,
|
||||
module::{Module, ModuleVc},
|
||||
reference::AssetReferencesVc,
|
||||
asset::{Asset, AssetContent},
|
||||
chunk::{availability_info::AvailabilityInfo, Chunk, ChunkableModule, ChunkingContext},
|
||||
ident::AssetIdent,
|
||||
module::Module,
|
||||
reference::AssetReferences,
|
||||
},
|
||||
ecmascript::chunk::EcmascriptChunkingContextVc,
|
||||
ecmascript::chunk::EcmascriptChunkingContext,
|
||||
turbopack::ecmascript::chunk::{
|
||||
EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc,
|
||||
EcmascriptChunkVc, EcmascriptExportsVc,
|
||||
EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkPlaceable, EcmascriptExports,
|
||||
},
|
||||
};
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn modifier() -> StringVc {
|
||||
StringVc::cell("in chunking context".to_string())
|
||||
fn modifier() -> Vc<String> {
|
||||
Vc::cell("in chunking context".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct InChunkingContextAsset {
|
||||
pub asset: EcmascriptChunkPlaceableVc,
|
||||
pub chunking_context: ChunkingContextVc,
|
||||
pub asset: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
pub chunking_context: Vc<Box<dyn ChunkingContext>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Asset for InChunkingContextAsset {
|
||||
#[turbo_tasks::function]
|
||||
fn ident(&self) -> AssetIdentVc {
|
||||
fn ident(&self) -> Vc<AssetIdent> {
|
||||
self.asset.ident().with_modifier(modifier())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn content(&self) -> AssetContentVc {
|
||||
fn content(&self) -> Vc<AssetContent> {
|
||||
self.asset.content()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn references(&self) -> AssetReferencesVc {
|
||||
fn references(&self) -> Vc<AssetReferences> {
|
||||
self.asset.references()
|
||||
}
|
||||
}
|
||||
|
@ -55,10 +51,14 @@ impl ChunkableModule for InChunkingContextAsset {
|
|||
#[turbo_tasks::function]
|
||||
fn as_chunk(
|
||||
&self,
|
||||
_context: ChunkingContextVc,
|
||||
_context: Vc<Box<dyn ChunkingContext>>,
|
||||
availability_info: Value<AvailabilityInfo>,
|
||||
) -> ChunkVc {
|
||||
EcmascriptChunkVc::new(self.chunking_context, self.asset, availability_info).into()
|
||||
) -> Vc<Box<dyn Chunk>> {
|
||||
Vc::upcast(EcmascriptChunk::new(
|
||||
self.chunking_context,
|
||||
self.asset,
|
||||
availability_info,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,10 +67,11 @@ impl EcmascriptChunkPlaceable for InChunkingContextAsset {
|
|||
#[turbo_tasks::function]
|
||||
async fn as_chunk_item(
|
||||
&self,
|
||||
_context: EcmascriptChunkingContextVc,
|
||||
) -> Result<EcmascriptChunkItemVc> {
|
||||
_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
) -> Result<Vc<Box<dyn EcmascriptChunkItem>>> {
|
||||
let Some(chunking_context) =
|
||||
EcmascriptChunkingContextVc::resolve_from(&self.chunking_context).await?
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkingContext>>(self.chunking_context)
|
||||
.await?
|
||||
else {
|
||||
bail!("chunking context is not an EcmascriptChunkingContext")
|
||||
};
|
||||
|
@ -78,7 +79,7 @@ impl EcmascriptChunkPlaceable for InChunkingContextAsset {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn get_exports(&self) -> EcmascriptExportsVc {
|
||||
fn get_exports(&self) -> Vc<EcmascriptExports> {
|
||||
self.asset.get_exports()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,4 +2,4 @@ pub(crate) mod client_chunks_transition;
|
|||
pub(crate) mod in_chunking_context_asset;
|
||||
pub(crate) mod with_chunks;
|
||||
|
||||
pub use client_chunks_transition::NextClientChunksTransitionVc;
|
||||
pub use client_chunks_transition::NextClientChunksTransition;
|
||||
|
|
|
@ -2,30 +2,29 @@ use std::io::Write;
|
|||
|
||||
use anyhow::Result;
|
||||
use indoc::writedoc;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::{
|
||||
tasks::{primitives::StringVc, TryJoinIterExt, Value},
|
||||
tasks::{TryJoinIterExt, Value},
|
||||
tasks_fs::rope::RopeBuilder,
|
||||
},
|
||||
turbopack::{
|
||||
core::{
|
||||
asset::{Asset, AssetContentVc, AssetVc},
|
||||
asset::{Asset, AssetContent},
|
||||
chunk::{
|
||||
availability_info::AvailabilityInfo, ChunkDataVc, ChunkGroupReferenceVc, ChunkItem,
|
||||
ChunkItemVc, ChunkVc, ChunkableModule, ChunkableModuleVc, ChunkingContext,
|
||||
ChunkingContextVc, ChunksDataVc,
|
||||
availability_info::AvailabilityInfo, Chunk, ChunkData, ChunkGroupReference,
|
||||
ChunkItem, ChunkableModule, ChunkingContext, ChunksData,
|
||||
},
|
||||
ident::AssetIdentVc,
|
||||
module::{Module, ModuleVc},
|
||||
output::OutputAssetsVc,
|
||||
reference::AssetReferencesVc,
|
||||
ident::AssetIdent,
|
||||
module::Module,
|
||||
output::OutputAssets,
|
||||
reference::AssetReferences,
|
||||
},
|
||||
ecmascript::{
|
||||
chunk::{
|
||||
EcmascriptChunkData, EcmascriptChunkItem, EcmascriptChunkItemContent,
|
||||
EcmascriptChunkItemContentVc, EcmascriptChunkItemVc, EcmascriptChunkPlaceable,
|
||||
EcmascriptChunkPlaceableVc, EcmascriptChunkVc, EcmascriptChunkingContextVc,
|
||||
EcmascriptExports, EcmascriptExportsVc,
|
||||
EcmascriptChunk, EcmascriptChunkData, EcmascriptChunkItem,
|
||||
EcmascriptChunkItemContent, EcmascriptChunkItemExt, EcmascriptChunkPlaceable,
|
||||
EcmascriptChunkingContext, EcmascriptExports,
|
||||
},
|
||||
utils::StringifyJs,
|
||||
},
|
||||
|
@ -33,18 +32,18 @@ use turbopack_binding::{
|
|||
};
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn modifier() -> StringVc {
|
||||
StringVc::cell("chunks".to_string())
|
||||
fn modifier() -> Vc<String> {
|
||||
Vc::cell("chunks".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::value]
|
||||
pub struct WithChunksAsset {
|
||||
asset: EcmascriptChunkPlaceableVc,
|
||||
chunking_context: EcmascriptChunkingContextVc,
|
||||
asset: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl WithChunksAssetVc {
|
||||
impl WithChunksAsset {
|
||||
/// Create a new [`WithChunksAsset`].
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -53,23 +52,23 @@ impl WithChunksAssetVc {
|
|||
/// * `chunking_context` - The chunking context of the asset.
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(
|
||||
asset: EcmascriptChunkPlaceableVc,
|
||||
chunking_context: EcmascriptChunkingContextVc,
|
||||
) -> WithChunksAssetVc {
|
||||
WithChunksAssetVc::cell(WithChunksAsset {
|
||||
asset: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
) -> Vc<WithChunksAsset> {
|
||||
WithChunksAsset::cell(WithChunksAsset {
|
||||
asset,
|
||||
chunking_context,
|
||||
})
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn entry_chunk(self) -> Result<ChunkVc> {
|
||||
async fn entry_chunk(self: Vc<Self>) -> Result<Vc<Box<dyn Chunk>>> {
|
||||
let this = self.await?;
|
||||
Ok(this.asset.as_root_chunk(this.chunking_context.into()))
|
||||
Ok(this.asset.as_root_chunk(Vc::upcast(this.chunking_context)))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn chunks(self) -> Result<OutputAssetsVc> {
|
||||
async fn chunks(self: Vc<Self>) -> Result<Vc<OutputAssets>> {
|
||||
let this = self.await?;
|
||||
Ok(this.chunking_context.chunk_group(self.entry_chunk()))
|
||||
}
|
||||
|
@ -78,25 +77,24 @@ impl WithChunksAssetVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Asset for WithChunksAsset {
|
||||
#[turbo_tasks::function]
|
||||
fn ident(&self) -> AssetIdentVc {
|
||||
fn ident(&self) -> Vc<AssetIdent> {
|
||||
self.asset.ident().with_modifier(modifier())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn content(&self) -> AssetContentVc {
|
||||
fn content(&self) -> Vc<AssetContent> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn references(self_vc: WithChunksAssetVc) -> Result<AssetReferencesVc> {
|
||||
let this = self_vc.await?;
|
||||
let entry_chunk = self_vc.entry_chunk();
|
||||
async fn references(self: Vc<Self>) -> Result<Vc<AssetReferences>> {
|
||||
let this = self.await?;
|
||||
let entry_chunk = self.entry_chunk();
|
||||
|
||||
Ok(AssetReferencesVc::cell(vec![ChunkGroupReferenceVc::new(
|
||||
this.chunking_context.into(),
|
||||
Ok(Vc::cell(vec![Vc::upcast(ChunkGroupReference::new(
|
||||
Vc::upcast(this.chunking_context),
|
||||
entry_chunk,
|
||||
)
|
||||
.into()]))
|
||||
))]))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,16 +105,15 @@ impl Module for WithChunksAsset {}
|
|||
impl ChunkableModule for WithChunksAsset {
|
||||
#[turbo_tasks::function]
|
||||
fn as_chunk(
|
||||
self_vc: WithChunksAssetVc,
|
||||
context: ChunkingContextVc,
|
||||
self: Vc<Self>,
|
||||
context: Vc<Box<dyn ChunkingContext>>,
|
||||
availability_info: Value<AvailabilityInfo>,
|
||||
) -> ChunkVc {
|
||||
EcmascriptChunkVc::new(
|
||||
) -> Vc<Box<dyn Chunk>> {
|
||||
Vc::upcast(EcmascriptChunk::new(
|
||||
context,
|
||||
self_vc.as_ecmascript_chunk_placeable(),
|
||||
Vc::upcast(self),
|
||||
availability_info,
|
||||
)
|
||||
.into()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,19 +121,20 @@ impl ChunkableModule for WithChunksAsset {
|
|||
impl EcmascriptChunkPlaceable for WithChunksAsset {
|
||||
#[turbo_tasks::function]
|
||||
async fn as_chunk_item(
|
||||
self_vc: WithChunksAssetVc,
|
||||
context: EcmascriptChunkingContextVc,
|
||||
) -> Result<EcmascriptChunkItemVc> {
|
||||
Ok(WithChunksChunkItem {
|
||||
context,
|
||||
inner: self_vc,
|
||||
}
|
||||
.cell()
|
||||
.into())
|
||||
self: Vc<Self>,
|
||||
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
) -> Result<Vc<Box<dyn EcmascriptChunkItem>>> {
|
||||
Ok(Vc::upcast(
|
||||
WithChunksChunkItem {
|
||||
context,
|
||||
inner: self,
|
||||
}
|
||||
.cell(),
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn get_exports(&self) -> EcmascriptExportsVc {
|
||||
fn get_exports(&self) -> Vc<EcmascriptExports> {
|
||||
// TODO This should be EsmExports
|
||||
EcmascriptExports::Value.cell()
|
||||
}
|
||||
|
@ -144,17 +142,17 @@ impl EcmascriptChunkPlaceable for WithChunksAsset {
|
|||
|
||||
#[turbo_tasks::value]
|
||||
struct WithChunksChunkItem {
|
||||
context: EcmascriptChunkingContextVc,
|
||||
inner: WithChunksAssetVc,
|
||||
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
inner: Vc<WithChunksAsset>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl WithChunksChunkItemVc {
|
||||
impl WithChunksChunkItem {
|
||||
#[turbo_tasks::function]
|
||||
async fn chunks_data(self) -> Result<ChunksDataVc> {
|
||||
async fn chunks_data(self: Vc<Self>) -> Result<Vc<ChunksData>> {
|
||||
let this = self.await?;
|
||||
let inner = this.inner.await?;
|
||||
Ok(ChunkDataVc::from_assets(
|
||||
Ok(ChunkData::from_assets(
|
||||
inner.chunking_context.output_root(),
|
||||
this.inner.chunks(),
|
||||
))
|
||||
|
@ -164,16 +162,16 @@ impl WithChunksChunkItemVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl EcmascriptChunkItem for WithChunksChunkItem {
|
||||
#[turbo_tasks::function]
|
||||
fn chunking_context(&self) -> EcmascriptChunkingContextVc {
|
||||
fn chunking_context(&self) -> Vc<Box<dyn EcmascriptChunkingContext>> {
|
||||
self.context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn content(self_vc: WithChunksChunkItemVc) -> Result<EcmascriptChunkItemContentVc> {
|
||||
let this = self_vc.await?;
|
||||
async fn content(self: Vc<Self>) -> Result<Vc<EcmascriptChunkItemContent>> {
|
||||
let this = self.await?;
|
||||
let inner = this.inner.await?;
|
||||
|
||||
let chunks_data = self_vc.chunks_data().await?;
|
||||
let chunks_data = self.chunks_data().await?;
|
||||
let chunks_data = chunks_data.iter().try_join().await?;
|
||||
let chunks_data: Vec<_> = chunks_data
|
||||
.iter()
|
||||
|
@ -212,18 +210,18 @@ impl EcmascriptChunkItem for WithChunksChunkItem {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ChunkItem for WithChunksChunkItem {
|
||||
#[turbo_tasks::function]
|
||||
fn asset_ident(&self) -> AssetIdentVc {
|
||||
fn asset_ident(&self) -> Vc<AssetIdent> {
|
||||
self.inner.ident()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn references(self_vc: WithChunksChunkItemVc) -> Result<AssetReferencesVc> {
|
||||
let mut references = self_vc.await?.inner.references().await?.clone_value();
|
||||
async fn references(self: Vc<Self>) -> Result<Vc<AssetReferences>> {
|
||||
let mut references = self.await?.inner.references().await?.clone_value();
|
||||
|
||||
for chunk_data in &*self_vc.chunks_data().await? {
|
||||
for chunk_data in &*self.chunks_data().await? {
|
||||
references.extend(chunk_data.references().await?.iter().copied());
|
||||
}
|
||||
|
||||
Ok(AssetReferencesVc::cell(references))
|
||||
Ok(Vc::cell(references))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
use anyhow::Result;
|
||||
use indexmap::indexmap;
|
||||
use turbo_tasks::Value;
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
context::AssetContext,
|
||||
module::ModuleVc,
|
||||
reference_type::{EntryReferenceSubType, InnerAssetsVc, ReferenceType},
|
||||
source::SourceVc,
|
||||
},
|
||||
turbopack::{
|
||||
transition::{Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
module::Module,
|
||||
reference_type::{EntryReferenceSubType, ReferenceType},
|
||||
source::Source,
|
||||
},
|
||||
turbopack::{transition::Transition, ModuleAssetContext},
|
||||
};
|
||||
|
||||
use crate::embed_js::next_asset;
|
||||
|
@ -25,43 +22,47 @@ pub struct NextServerToClientTransition {
|
|||
impl Transition for NextServerToClientTransition {
|
||||
#[turbo_tasks::function]
|
||||
async fn process(
|
||||
self_vc: NextServerToClientTransitionVc,
|
||||
source: SourceVc,
|
||||
context: ModuleAssetContextVc,
|
||||
self: Vc<Self>,
|
||||
source: Vc<Box<dyn Source>>,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
_reference_type: Value<ReferenceType>,
|
||||
) -> Result<ModuleVc> {
|
||||
let this = self_vc.await?;
|
||||
let context = self_vc.process_context(context);
|
||||
let client_chunks = context.with_transition("next-client-chunks").process(
|
||||
source,
|
||||
Value::new(ReferenceType::Entry(
|
||||
EntryReferenceSubType::AppClientComponent,
|
||||
)),
|
||||
);
|
||||
) -> Result<Vc<Box<dyn Module>>> {
|
||||
let this = self.await?;
|
||||
let context = self.process_context(context);
|
||||
let client_chunks = context
|
||||
.with_transition("next-client-chunks".to_string())
|
||||
.process(
|
||||
source,
|
||||
Value::new(ReferenceType::Entry(
|
||||
EntryReferenceSubType::AppClientComponent,
|
||||
)),
|
||||
);
|
||||
|
||||
Ok(match this.ssr {
|
||||
true => {
|
||||
let internal_source = next_asset("entry/app/server-to-client-ssr.tsx");
|
||||
let client_module = context.with_transition("next-ssr-client-module").process(
|
||||
source,
|
||||
Value::new(ReferenceType::Entry(
|
||||
EntryReferenceSubType::AppClientComponent,
|
||||
)),
|
||||
);
|
||||
let internal_source = next_asset("entry/app/server-to-client-ssr.tsx".to_string());
|
||||
let client_module = context
|
||||
.with_transition("next-ssr-client-module".to_string())
|
||||
.process(
|
||||
source,
|
||||
Value::new(ReferenceType::Entry(
|
||||
EntryReferenceSubType::AppClientComponent,
|
||||
)),
|
||||
);
|
||||
context.process(
|
||||
internal_source,
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap! {
|
||||
"CLIENT_MODULE".to_string() => client_module.into(),
|
||||
"CLIENT_CHUNKS".to_string() => client_chunks.into(),
|
||||
Value::new(ReferenceType::Internal(Vc::cell(indexmap! {
|
||||
"CLIENT_MODULE".to_string() => Vc::upcast(client_module),
|
||||
"CLIENT_CHUNKS".to_string() => Vc::upcast(client_chunks),
|
||||
}))),
|
||||
)
|
||||
}
|
||||
false => {
|
||||
let internal_source = next_asset("entry/app/server-to-client.tsx");
|
||||
let internal_source = next_asset("entry/app/server-to-client.tsx".to_string());
|
||||
context.process(
|
||||
internal_source,
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap! {
|
||||
"CLIENT_CHUNKS".to_string() => client_chunks.into(),
|
||||
Value::new(ReferenceType::Internal(Vc::cell(indexmap! {
|
||||
"CLIENT_CHUNKS".to_string() => Vc::upcast(client_chunks),
|
||||
}))),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
use anyhow::Result;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{compile_time_info::CompileTimeInfoVc, module::ModuleVc},
|
||||
core::{compile_time_info::CompileTimeInfo, module::Module},
|
||||
turbopack::{
|
||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
||||
module_options::ModuleOptionsContextVc,
|
||||
resolve_options_context::ResolveOptionsContextVc,
|
||||
transition::{Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
ecmascript::chunk::EcmascriptChunkPlaceable, module_options::ModuleOptionsContext,
|
||||
resolve_options_context::ResolveOptionsContext, transition::Transition, ModuleAssetContext,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -14,9 +12,9 @@ use super::with_chunking_context_scope_asset::WithChunkingContextScopeAsset;
|
|||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextSSRClientModuleTransition {
|
||||
pub ssr_environment: CompileTimeInfoVc,
|
||||
pub ssr_module_options_context: ModuleOptionsContextVc,
|
||||
pub ssr_resolve_options_context: ResolveOptionsContextVc,
|
||||
pub ssr_environment: Vc<CompileTimeInfo>,
|
||||
pub ssr_module_options_context: Vc<ModuleOptionsContext>,
|
||||
pub ssr_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
|
@ -24,41 +22,44 @@ impl Transition for NextSSRClientModuleTransition {
|
|||
#[turbo_tasks::function]
|
||||
fn process_compile_time_info(
|
||||
&self,
|
||||
_compile_time_info: CompileTimeInfoVc,
|
||||
) -> CompileTimeInfoVc {
|
||||
_compile_time_info: Vc<CompileTimeInfo>,
|
||||
) -> Vc<CompileTimeInfo> {
|
||||
self.ssr_environment
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_module_options_context(
|
||||
&self,
|
||||
_context: ModuleOptionsContextVc,
|
||||
) -> ModuleOptionsContextVc {
|
||||
_context: Vc<ModuleOptionsContext>,
|
||||
) -> Vc<ModuleOptionsContext> {
|
||||
self.ssr_module_options_context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_resolve_options_context(
|
||||
&self,
|
||||
_context: ResolveOptionsContextVc,
|
||||
) -> ResolveOptionsContextVc {
|
||||
_context: Vc<ResolveOptionsContext>,
|
||||
) -> Vc<ResolveOptionsContext> {
|
||||
self.ssr_resolve_options_context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn process_module(
|
||||
&self,
|
||||
asset: ModuleVc,
|
||||
_context: ModuleAssetContextVc,
|
||||
) -> Result<ModuleVc> {
|
||||
asset: Vc<Box<dyn Module>>,
|
||||
_context: Vc<ModuleAssetContext>,
|
||||
) -> Result<Vc<Box<dyn Module>>> {
|
||||
Ok(
|
||||
if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? {
|
||||
WithChunkingContextScopeAsset {
|
||||
asset: placeable,
|
||||
layer: "ssr".to_string(),
|
||||
}
|
||||
.cell()
|
||||
.into()
|
||||
if let Some(placeable) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(asset).await?
|
||||
{
|
||||
Vc::upcast(
|
||||
WithChunkingContextScopeAsset {
|
||||
asset: placeable,
|
||||
layer: "ssr".to_string(),
|
||||
}
|
||||
.cell(),
|
||||
)
|
||||
} else {
|
||||
asset
|
||||
},
|
||||
|
|
|
@ -1,48 +1,44 @@
|
|||
use anyhow::{Context, Result};
|
||||
use turbo_tasks::{primitives::StringVc, Value};
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
asset::{Asset, AssetContentVc, AssetVc},
|
||||
chunk::{
|
||||
availability_info::AvailabilityInfo, ChunkVc, ChunkableModule, ChunkableModuleVc,
|
||||
ChunkingContext, ChunkingContextVc,
|
||||
},
|
||||
ident::AssetIdentVc,
|
||||
module::{Module, ModuleVc},
|
||||
reference::AssetReferencesVc,
|
||||
asset::{Asset, AssetContent},
|
||||
chunk::{availability_info::AvailabilityInfo, Chunk, ChunkableModule, ChunkingContext},
|
||||
ident::AssetIdent,
|
||||
module::Module,
|
||||
reference::AssetReferences,
|
||||
},
|
||||
ecmascript::chunk::EcmascriptChunkingContextVc,
|
||||
ecmascript::chunk::EcmascriptChunkingContext,
|
||||
turbopack::ecmascript::chunk::{
|
||||
EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc,
|
||||
EcmascriptChunkVc, EcmascriptExportsVc,
|
||||
EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkPlaceable, EcmascriptExports,
|
||||
},
|
||||
};
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn modifier() -> StringVc {
|
||||
StringVc::cell("with chunking context scope".to_string())
|
||||
fn modifier() -> Vc<String> {
|
||||
Vc::cell("with chunking context scope".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct WithChunkingContextScopeAsset {
|
||||
pub asset: EcmascriptChunkPlaceableVc,
|
||||
pub asset: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
pub layer: String,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Asset for WithChunkingContextScopeAsset {
|
||||
#[turbo_tasks::function]
|
||||
fn ident(&self) -> AssetIdentVc {
|
||||
fn ident(&self) -> Vc<AssetIdent> {
|
||||
self.asset.ident().with_modifier(modifier())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn content(&self) -> AssetContentVc {
|
||||
fn content(&self) -> Vc<AssetContent> {
|
||||
self.asset.content()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn references(&self) -> AssetReferencesVc {
|
||||
fn references(&self) -> Vc<AssetReferences> {
|
||||
self.asset.references()
|
||||
}
|
||||
}
|
||||
|
@ -55,15 +51,14 @@ impl ChunkableModule for WithChunkingContextScopeAsset {
|
|||
#[turbo_tasks::function]
|
||||
fn as_chunk(
|
||||
&self,
|
||||
context: ChunkingContextVc,
|
||||
context: Vc<Box<dyn ChunkingContext>>,
|
||||
availability_info: Value<AvailabilityInfo>,
|
||||
) -> ChunkVc {
|
||||
EcmascriptChunkVc::new(
|
||||
context.with_layer(&self.layer),
|
||||
) -> Vc<Box<dyn Chunk>> {
|
||||
Vc::upcast(EcmascriptChunk::new(
|
||||
context.with_layer(self.layer.clone()),
|
||||
self.asset,
|
||||
availability_info,
|
||||
)
|
||||
.into()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,20 +67,22 @@ impl EcmascriptChunkPlaceable for WithChunkingContextScopeAsset {
|
|||
#[turbo_tasks::function]
|
||||
async fn as_chunk_item(
|
||||
&self,
|
||||
context: EcmascriptChunkingContextVc,
|
||||
) -> Result<EcmascriptChunkItemVc> {
|
||||
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
) -> Result<Vc<Box<dyn EcmascriptChunkItem>>> {
|
||||
Ok(self.asset.as_chunk_item(
|
||||
EcmascriptChunkingContextVc::resolve_from(context.with_layer(&self.layer))
|
||||
.await?
|
||||
.context(
|
||||
"ChunkingContextVc::with_layer should not return a different kind of chunking \
|
||||
context",
|
||||
)?,
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkingContext>>(
|
||||
context.with_layer(self.layer.clone()),
|
||||
)
|
||||
.await?
|
||||
.context(
|
||||
"ChunkingContext::with_layer should not return a different kind of chunking \
|
||||
context",
|
||||
)?,
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn get_exports(&self) -> EcmascriptExportsVc {
|
||||
fn get_exports(&self) -> Vc<EcmascriptExports> {
|
||||
self.asset.get_exports()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
use anyhow::{Context, Result};
|
||||
use indoc::formatdoc;
|
||||
use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value, ValueToString, ValueToStringVc};
|
||||
use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::FileSystemPathVc,
|
||||
turbo::tasks_fs::FileSystemPath,
|
||||
turbopack::{
|
||||
core::{
|
||||
asset::{Asset, AssetContentVc, AssetVc},
|
||||
asset::{Asset, AssetContent},
|
||||
chunk::{
|
||||
availability_info::AvailabilityInfo, ChunkDataVc, ChunkItem, ChunkItemVc, ChunkVc,
|
||||
ChunkableModule, ChunkableModuleReference, ChunkableModuleReferenceVc,
|
||||
ChunkableModuleVc, ChunkingContext, ChunkingContextVc, ChunkingType,
|
||||
ChunkingTypeOptionVc, ChunksDataVc,
|
||||
availability_info::AvailabilityInfo, Chunk, ChunkData, ChunkItem, ChunkableModule,
|
||||
ChunkableModuleReference, ChunkingContext, ChunkingType, ChunkingTypeOption,
|
||||
ChunksData,
|
||||
},
|
||||
ident::AssetIdentVc,
|
||||
module::{Module, ModuleVc},
|
||||
output::OutputAssetsVc,
|
||||
proxied_asset::ProxiedAssetVc,
|
||||
reference::{
|
||||
AssetReference, AssetReferenceVc, AssetReferencesVc, SingleAssetReferenceVc,
|
||||
},
|
||||
resolve::{ResolveResult, ResolveResultVc},
|
||||
ident::AssetIdent,
|
||||
module::Module,
|
||||
output::OutputAssets,
|
||||
proxied_asset::ProxiedAsset,
|
||||
reference::{AssetReference, AssetReferences, SingleAssetReference},
|
||||
resolve::ResolveResult,
|
||||
},
|
||||
ecmascript::chunk::EcmascriptChunkData,
|
||||
ecmascript::chunk::{EcmascriptChunkData, EcmascriptChunkItemExt},
|
||||
turbopack::ecmascript::{
|
||||
chunk::{
|
||||
EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc,
|
||||
EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc,
|
||||
EcmascriptChunkVc, EcmascriptChunkingContextVc, EcmascriptExports,
|
||||
EcmascriptExportsVc,
|
||||
EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkItemContent,
|
||||
EcmascriptChunkPlaceable, EcmascriptChunkingContext, EcmascriptExports,
|
||||
},
|
||||
utils::StringifyJs,
|
||||
},
|
||||
|
@ -35,35 +30,36 @@ use turbopack_binding::{
|
|||
};
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn modifier() -> StringVc {
|
||||
StringVc::cell("client chunks".to_string())
|
||||
fn modifier() -> Vc<String> {
|
||||
Vc::cell("client chunks".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct WithClientChunksAsset {
|
||||
pub asset: EcmascriptChunkPlaceableVc,
|
||||
pub server_root: FileSystemPathVc,
|
||||
pub asset: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
pub server_root: Vc<FileSystemPath>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Asset for WithClientChunksAsset {
|
||||
#[turbo_tasks::function]
|
||||
fn ident(&self) -> AssetIdentVc {
|
||||
fn ident(&self) -> Vc<AssetIdent> {
|
||||
self.asset.ident().with_modifier(modifier())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn content(&self) -> AssetContentVc {
|
||||
fn content(&self) -> Vc<AssetContent> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn references(&self) -> AssetReferencesVc {
|
||||
AssetReferencesVc::cell(vec![WithClientChunksAssetReference {
|
||||
asset: self.asset.into(),
|
||||
}
|
||||
.cell()
|
||||
.into()])
|
||||
fn references(&self) -> Vc<AssetReferences> {
|
||||
Vc::cell(vec![Vc::upcast(
|
||||
WithClientChunksAssetReference {
|
||||
asset: Vc::upcast(self.asset),
|
||||
}
|
||||
.cell(),
|
||||
)])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,16 +70,15 @@ impl Module for WithClientChunksAsset {}
|
|||
impl ChunkableModule for WithClientChunksAsset {
|
||||
#[turbo_tasks::function]
|
||||
fn as_chunk(
|
||||
self_vc: WithClientChunksAssetVc,
|
||||
context: ChunkingContextVc,
|
||||
self: Vc<Self>,
|
||||
context: Vc<Box<dyn ChunkingContext>>,
|
||||
availability_info: Value<AvailabilityInfo>,
|
||||
) -> ChunkVc {
|
||||
EcmascriptChunkVc::new(
|
||||
context.with_layer("rsc"),
|
||||
self_vc.as_ecmascript_chunk_placeable(),
|
||||
) -> Vc<Box<dyn Chunk>> {
|
||||
Vc::upcast(EcmascriptChunk::new(
|
||||
context.with_layer("rsc".to_string()),
|
||||
Vc::upcast(self),
|
||||
availability_info,
|
||||
)
|
||||
.into()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,24 +86,27 @@ impl ChunkableModule for WithClientChunksAsset {
|
|||
impl EcmascriptChunkPlaceable for WithClientChunksAsset {
|
||||
#[turbo_tasks::function]
|
||||
async fn as_chunk_item(
|
||||
self_vc: WithClientChunksAssetVc,
|
||||
context: EcmascriptChunkingContextVc,
|
||||
) -> Result<EcmascriptChunkItemVc> {
|
||||
Ok(WithClientChunksChunkItem {
|
||||
context: EcmascriptChunkingContextVc::resolve_from(context.with_layer("rsc"))
|
||||
self: Vc<Self>,
|
||||
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
) -> Result<Vc<Box<dyn EcmascriptChunkItem>>> {
|
||||
Ok(Vc::upcast(
|
||||
WithClientChunksChunkItem {
|
||||
context: Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkingContext>>(
|
||||
context.with_layer("rsc".to_string()),
|
||||
)
|
||||
.await?
|
||||
.context(
|
||||
"ChunkingContextVc::with_layer should not return a different kind of chunking \
|
||||
"ChunkingContext::with_layer should not return a different kind of chunking \
|
||||
context",
|
||||
)?,
|
||||
inner: self_vc,
|
||||
}
|
||||
.cell()
|
||||
.into())
|
||||
inner: self,
|
||||
}
|
||||
.cell(),
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn get_exports(&self) -> EcmascriptExportsVc {
|
||||
fn get_exports(&self) -> Vc<EcmascriptExports> {
|
||||
// TODO This should be EsmExports
|
||||
EcmascriptExports::Value.cell()
|
||||
}
|
||||
|
@ -116,23 +114,23 @@ impl EcmascriptChunkPlaceable for WithClientChunksAsset {
|
|||
|
||||
#[turbo_tasks::value]
|
||||
struct WithClientChunksChunkItem {
|
||||
context: EcmascriptChunkingContextVc,
|
||||
inner: WithClientChunksAssetVc,
|
||||
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
inner: Vc<WithClientChunksAsset>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl WithClientChunksChunkItemVc {
|
||||
impl WithClientChunksChunkItem {
|
||||
#[turbo_tasks::function]
|
||||
async fn chunks(self) -> Result<OutputAssetsVc> {
|
||||
async fn chunks(self: Vc<Self>) -> Result<Vc<OutputAssets>> {
|
||||
let this = self.await?;
|
||||
let inner = this.inner.await?;
|
||||
Ok(this
|
||||
.context
|
||||
.chunk_group(inner.asset.as_root_chunk(this.context.into())))
|
||||
.chunk_group(inner.asset.as_root_chunk(Vc::upcast(this.context))))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn client_chunks(self) -> Result<OutputAssetsVc> {
|
||||
async fn client_chunks(self: Vc<Self>) -> Result<Vc<OutputAssets>> {
|
||||
let this = self.await?;
|
||||
let inner = this.inner.await?;
|
||||
let chunks = self.chunks();
|
||||
|
@ -144,21 +142,22 @@ impl WithClientChunksChunkItemVc {
|
|||
// Only expose CSS chunks as client chunks.
|
||||
if &*extension == "css" {
|
||||
if let Some(path) = output_root.get_path_to(&*chunk.ident().path().await?) {
|
||||
client_chunks.push(
|
||||
ProxiedAssetVc::new(chunk.into(), inner.server_root.join(path)).into(),
|
||||
);
|
||||
client_chunks.push(Vc::upcast(ProxiedAsset::new(
|
||||
Vc::upcast(chunk),
|
||||
inner.server_root.join(path.to_string()),
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(OutputAssetsVc::cell(client_chunks))
|
||||
Ok(Vc::cell(client_chunks))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn chunks_data(self) -> Result<ChunksDataVc> {
|
||||
async fn chunks_data(self: Vc<Self>) -> Result<Vc<ChunksData>> {
|
||||
let this = self.await?;
|
||||
let inner = this.inner.await?;
|
||||
Ok(ChunkDataVc::from_assets(
|
||||
Ok(ChunkData::from_assets(
|
||||
inner.server_root,
|
||||
self.client_chunks(),
|
||||
))
|
||||
|
@ -168,16 +167,16 @@ impl WithClientChunksChunkItemVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl EcmascriptChunkItem for WithClientChunksChunkItem {
|
||||
#[turbo_tasks::function]
|
||||
fn chunking_context(&self) -> EcmascriptChunkingContextVc {
|
||||
fn chunking_context(&self) -> Vc<Box<dyn EcmascriptChunkingContext>> {
|
||||
self.context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn content(self_vc: WithClientChunksChunkItemVc) -> Result<EcmascriptChunkItemContentVc> {
|
||||
let this = self_vc.await?;
|
||||
async fn content(self: Vc<Self>) -> Result<Vc<EcmascriptChunkItemContent>> {
|
||||
let this = self.await?;
|
||||
let inner = this.inner.await?;
|
||||
|
||||
let chunks_data = self_vc.chunks_data().await?;
|
||||
let chunks_data = self.chunks_data().await?;
|
||||
let chunks_data = chunks_data.iter().try_join().await?;
|
||||
let chunks_data: Vec<_> = chunks_data
|
||||
.iter()
|
||||
|
@ -209,45 +208,47 @@ impl EcmascriptChunkItem for WithClientChunksChunkItem {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ChunkItem for WithClientChunksChunkItem {
|
||||
#[turbo_tasks::function]
|
||||
fn asset_ident(&self) -> AssetIdentVc {
|
||||
fn asset_ident(&self) -> Vc<AssetIdent> {
|
||||
self.inner.ident()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn references(self_vc: WithClientChunksChunkItemVc) -> Result<AssetReferencesVc> {
|
||||
let this = self_vc.await?;
|
||||
async fn references(self: Vc<Self>) -> Result<Vc<AssetReferences>> {
|
||||
let this = self.await?;
|
||||
let inner = this.inner.await?;
|
||||
let mut references = Vec::new();
|
||||
references.push(
|
||||
references.push(Vc::upcast(
|
||||
WithClientChunksAssetReference {
|
||||
asset: inner.asset.into(),
|
||||
asset: Vc::upcast(inner.asset),
|
||||
}
|
||||
.cell()
|
||||
.into(),
|
||||
);
|
||||
let client_chunks = self_vc.client_chunks();
|
||||
.cell(),
|
||||
));
|
||||
let client_chunks = self.client_chunks();
|
||||
let client_chunks = client_chunks.await?;
|
||||
let client_chunk = StringVc::cell("client chunk".to_string());
|
||||
let client_chunk = Vc::cell("client chunk".to_string());
|
||||
for &chunk in client_chunks.iter() {
|
||||
references.push(SingleAssetReferenceVc::new(chunk.into(), client_chunk).into());
|
||||
references.push(Vc::upcast(SingleAssetReference::new(
|
||||
Vc::upcast(chunk),
|
||||
client_chunk,
|
||||
)));
|
||||
}
|
||||
for chunk_data in &*self_vc.chunks_data().await? {
|
||||
for chunk_data in &*self.chunks_data().await? {
|
||||
references.extend(chunk_data.references().await?.iter().copied());
|
||||
}
|
||||
Ok(AssetReferencesVc::cell(references))
|
||||
Ok(Vc::cell(references))
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value]
|
||||
struct WithClientChunksAssetReference {
|
||||
asset: AssetVc,
|
||||
asset: Vc<Box<dyn Asset>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ValueToString for WithClientChunksAssetReference {
|
||||
#[turbo_tasks::function]
|
||||
async fn to_string(&self) -> Result<StringVc> {
|
||||
Ok(StringVc::cell(format!(
|
||||
async fn to_string(&self) -> Result<Vc<String>> {
|
||||
Ok(Vc::cell(format!(
|
||||
"local asset {}",
|
||||
self.asset.ident().to_string().await?
|
||||
)))
|
||||
|
@ -257,7 +258,7 @@ impl ValueToString for WithClientChunksAssetReference {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl AssetReference for WithClientChunksAssetReference {
|
||||
#[turbo_tasks::function]
|
||||
fn resolve_reference(&self) -> ResolveResultVc {
|
||||
fn resolve_reference(&self) -> Vc<ResolveResult> {
|
||||
ResolveResult::asset(self.asset).cell()
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +266,7 @@ impl AssetReference for WithClientChunksAssetReference {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ChunkableModuleReference for WithClientChunksAssetReference {
|
||||
#[turbo_tasks::function]
|
||||
fn chunking_type(&self) -> ChunkingTypeOptionVc {
|
||||
ChunkingTypeOptionVc::cell(Some(ChunkingType::IsolatedParallel))
|
||||
fn chunking_type(&self) -> Vc<ChunkingTypeOption> {
|
||||
Vc::cell(Some(ChunkingType::IsolatedParallel))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,63 +1,65 @@
|
|||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::primitives::StringVc;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
asset::{Asset, AssetContentVc, AssetVc},
|
||||
ident::AssetIdentVc,
|
||||
module::{Module, ModuleVc},
|
||||
reference::AssetReferencesVc,
|
||||
asset::{Asset, AssetContent},
|
||||
ident::AssetIdent,
|
||||
module::Module,
|
||||
reference::AssetReferences,
|
||||
},
|
||||
turbopack::css::{chunk::CssChunkPlaceableVc, ParseCss, ParseCssResultVc, ParseCssVc},
|
||||
turbopack::css::{chunk::CssChunkPlaceable, ParseCss, ParseCssResult},
|
||||
};
|
||||
|
||||
/// A [`CssClientReferenceModule`] is a marker module used to indicate which
|
||||
/// client reference should appear in the client reference manifest.
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub struct CssClientReferenceModule {
|
||||
pub client_module: CssChunkPlaceableVc,
|
||||
pub client_module: Vc<Box<dyn CssChunkPlaceable>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl CssClientReferenceModuleVc {
|
||||
impl CssClientReferenceModule {
|
||||
/// Create a new [`CssClientReferenceModule`] from the given source CSS
|
||||
/// module.
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(client_module: CssChunkPlaceableVc) -> CssClientReferenceModuleVc {
|
||||
pub fn new(client_module: Vc<Box<dyn CssChunkPlaceable>>) -> Vc<CssClientReferenceModule> {
|
||||
CssClientReferenceModule { client_module }.cell()
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn css_client_reference_modifier() -> StringVc {
|
||||
StringVc::cell("css client reference".to_string())
|
||||
fn css_client_reference_modifier() -> Vc<String> {
|
||||
Vc::cell("css client reference".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Asset for CssClientReferenceModule {
|
||||
#[turbo_tasks::function]
|
||||
fn ident(&self) -> AssetIdentVc {
|
||||
fn ident(&self) -> Vc<AssetIdent> {
|
||||
self.client_module
|
||||
.ident()
|
||||
.with_modifier(css_client_reference_modifier())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn content(&self) -> Result<AssetContentVc> {
|
||||
fn content(&self) -> Result<Vc<AssetContent>> {
|
||||
// The client reference asset only serves as a marker asset.
|
||||
bail!("CssClientReferenceModule has no content")
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn references(_self_vc: CssClientReferenceModuleVc) -> AssetReferencesVc {
|
||||
AssetReferencesVc::empty()
|
||||
fn references(self: Vc<Self>) -> Vc<AssetReferences> {
|
||||
AssetReferences::empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ParseCss for CssClientReferenceModule {
|
||||
#[turbo_tasks::function]
|
||||
async fn parse_css(&self) -> Result<ParseCssResultVc> {
|
||||
let Some(parse_css) = ParseCssVc::resolve_from(self.client_module).await? else {
|
||||
async fn parse_css(&self) -> Result<Vc<ParseCssResult>> {
|
||||
let Some(parse_css) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn ParseCss>>(self.client_module).await?
|
||||
else {
|
||||
bail!("CSS client reference client module must be CSS parseable");
|
||||
};
|
||||
|
||||
|
|
|
@ -1,33 +1,31 @@
|
|||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::Value;
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
module::ModuleVc,
|
||||
module::Module,
|
||||
reference_type::{CssReferenceSubType, ReferenceType},
|
||||
resolve::ModulePartVc,
|
||||
source::SourceVc,
|
||||
resolve::ModulePart,
|
||||
source::Source,
|
||||
},
|
||||
turbopack::{
|
||||
css::chunk::CssChunkPlaceableVc,
|
||||
module_options::{CustomModuleType, CustomModuleTypeVc},
|
||||
transition::{Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
css::chunk::CssChunkPlaceable, module_options::CustomModuleType, transition::Transition,
|
||||
ModuleAssetContext,
|
||||
},
|
||||
};
|
||||
|
||||
use super::css_client_reference_module::CssClientReferenceModuleVc;
|
||||
use super::css_client_reference_module::CssClientReferenceModule;
|
||||
|
||||
/// Module type for CSS client references. This will be used to hook into CSS
|
||||
/// asset processing and inject a client reference on the server side.
|
||||
#[turbo_tasks::value]
|
||||
pub struct CssClientReferenceModuleType {
|
||||
client_transition: TransitionVc,
|
||||
client_transition: Vc<Box<dyn Transition>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl CssClientReferenceModuleTypeVc {
|
||||
impl CssClientReferenceModuleType {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(client_transition: TransitionVc) -> Self {
|
||||
pub fn new(client_transition: Vc<Box<dyn Transition>>) -> Vc<Self> {
|
||||
CssClientReferenceModuleType { client_transition }.cell()
|
||||
}
|
||||
}
|
||||
|
@ -37,20 +35,22 @@ impl CustomModuleType for CssClientReferenceModuleType {
|
|||
#[turbo_tasks::function]
|
||||
async fn create_module(
|
||||
&self,
|
||||
source: SourceVc,
|
||||
context: ModuleAssetContextVc,
|
||||
_part: Option<ModulePartVc>,
|
||||
) -> Result<ModuleVc> {
|
||||
source: Vc<Box<dyn Source>>,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
_part: Option<Vc<ModulePart>>,
|
||||
) -> Result<Vc<Box<dyn Module>>> {
|
||||
let client_module = self.client_transition.process(
|
||||
source,
|
||||
context,
|
||||
Value::new(ReferenceType::Css(CssReferenceSubType::Internal)),
|
||||
);
|
||||
|
||||
let Some(client_module) = CssChunkPlaceableVc::resolve_from(&client_module).await? else {
|
||||
let Some(client_module) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn CssChunkPlaceable>>(client_module).await?
|
||||
else {
|
||||
bail!("client asset is not CSS chunk placeable");
|
||||
};
|
||||
|
||||
Ok(CssClientReferenceModuleVc::new(client_module).into())
|
||||
Ok(Vc::upcast(CssClientReferenceModule::new(client_module)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::{
|
||||
core::reference_type::{CssReferenceSubType, ReferenceType},
|
||||
turbopack::{
|
||||
module_options::{ModuleRule, ModuleRuleCondition, ModuleRuleEffect, ModuleType},
|
||||
transition::TransitionVc,
|
||||
transition::Transition,
|
||||
},
|
||||
};
|
||||
|
||||
use super::css_client_reference_module_type::CssClientReferenceModuleTypeVc;
|
||||
use super::css_client_reference_module_type::CssClientReferenceModuleType;
|
||||
|
||||
pub(crate) fn get_next_css_client_reference_transforms_rule(
|
||||
client_transition: TransitionVc,
|
||||
client_transition: Vc<Box<dyn Transition>>,
|
||||
) -> ModuleRule {
|
||||
let module_type = CssClientReferenceModuleTypeVc::new(client_transition);
|
||||
let module_type = CssClientReferenceModuleType::new(client_transition);
|
||||
|
||||
ModuleRule::new_internal(
|
||||
// Override the default module type for CSS assets. Instead, they will go through the
|
||||
|
@ -22,7 +23,7 @@ pub(crate) fn get_next_css_client_reference_transforms_rule(
|
|||
ReferenceType::Css(CssReferenceSubType::Internal),
|
||||
)]),
|
||||
vec![ModuleRuleEffect::ModuleType(ModuleType::Custom(
|
||||
module_type.into(),
|
||||
Vc::upcast(module_type),
|
||||
))],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::primitives::StringVc;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
asset::{Asset, AssetContentVc, AssetVc},
|
||||
ident::AssetIdentVc,
|
||||
module::{Module, ModuleVc},
|
||||
reference::AssetReferencesVc,
|
||||
asset::{Asset, AssetContent},
|
||||
ident::AssetIdent,
|
||||
module::Module,
|
||||
reference::AssetReferences,
|
||||
},
|
||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
||||
ecmascript::chunk::EcmascriptChunkPlaceable,
|
||||
};
|
||||
|
||||
/// An [`EcmascriptClientReferenceModule`] is a marker module, used by the
|
||||
|
@ -15,13 +15,13 @@ use turbopack_binding::turbopack::{
|
|||
/// should appear in the client reference manifest.
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub struct EcmascriptClientReferenceModule {
|
||||
pub server_ident: AssetIdentVc,
|
||||
pub client_module: EcmascriptChunkPlaceableVc,
|
||||
pub ssr_module: EcmascriptChunkPlaceableVc,
|
||||
pub server_ident: Vc<AssetIdent>,
|
||||
pub client_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
pub ssr_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl EcmascriptClientReferenceModuleVc {
|
||||
impl EcmascriptClientReferenceModule {
|
||||
/// Create a new [`EcmascriptClientReferenceModule`].
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -32,10 +32,10 @@ impl EcmascriptClientReferenceModuleVc {
|
|||
/// * `ssr_module` - The SSR module.
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(
|
||||
server_ident: AssetIdentVc,
|
||||
client_module: EcmascriptChunkPlaceableVc,
|
||||
ssr_module: EcmascriptChunkPlaceableVc,
|
||||
) -> EcmascriptClientReferenceModuleVc {
|
||||
server_ident: Vc<AssetIdent>,
|
||||
client_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
ssr_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
) -> Vc<EcmascriptClientReferenceModule> {
|
||||
EcmascriptClientReferenceModule {
|
||||
server_ident,
|
||||
client_module,
|
||||
|
@ -46,27 +46,27 @@ impl EcmascriptClientReferenceModuleVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn ecmascript_client_reference_modifier() -> StringVc {
|
||||
StringVc::cell("ecmascript client reference".to_string())
|
||||
fn ecmascript_client_reference_modifier() -> Vc<String> {
|
||||
Vc::cell("ecmascript client reference".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Asset for EcmascriptClientReferenceModule {
|
||||
#[turbo_tasks::function]
|
||||
fn ident(&self) -> AssetIdentVc {
|
||||
fn ident(&self) -> Vc<AssetIdent> {
|
||||
self.server_ident
|
||||
.with_modifier(ecmascript_client_reference_modifier())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn content(&self) -> Result<AssetContentVc> {
|
||||
fn content(&self) -> Result<Vc<AssetContent>> {
|
||||
// The ES client reference asset only serves as a marker asset.
|
||||
bail!("EcmascriptClientReferenceModule has no content")
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn references(_self_vc: EcmascriptClientReferenceModuleVc) -> AssetReferencesVc {
|
||||
AssetReferencesVc::empty()
|
||||
fn references(self: Vc<Self>) -> Vc<AssetReferences> {
|
||||
AssetReferences::empty()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,48 +2,46 @@ use std::{io::Write, iter::once};
|
|||
|
||||
use anyhow::{bail, Result};
|
||||
use indoc::writedoc;
|
||||
use turbo_tasks::{primitives::StringVc, Value, ValueToString};
|
||||
use turbo_tasks::{Value, ValueToString, Vc};
|
||||
use turbo_tasks_fs::File;
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
asset::{Asset, AssetContentVc, AssetVc},
|
||||
asset::{Asset, AssetContent},
|
||||
chunk::{
|
||||
availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableModule,
|
||||
ChunkableModuleVc, ChunkingContextVc,
|
||||
availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableModule, ChunkingContext,
|
||||
},
|
||||
code_builder::CodeBuilder,
|
||||
context::{AssetContext, AssetContextVc},
|
||||
ident::AssetIdentVc,
|
||||
module::{Module, ModuleVc},
|
||||
reference::{AssetReferencesVc, SingleAssetReferenceVc},
|
||||
context::AssetContext,
|
||||
ident::AssetIdent,
|
||||
module::Module,
|
||||
reference::{AssetReferences, SingleAssetReference},
|
||||
reference_type::ReferenceType,
|
||||
virtual_source::VirtualSourceVc,
|
||||
virtual_source::VirtualSource,
|
||||
},
|
||||
ecmascript::{
|
||||
chunk::{
|
||||
EcmascriptChunkItem, EcmascriptChunkItemContentVc, EcmascriptChunkItemVc,
|
||||
EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkVc,
|
||||
EcmascriptChunkingContextVc, EcmascriptExportsVc,
|
||||
EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkItemContent,
|
||||
EcmascriptChunkPlaceable, EcmascriptChunkingContext, EcmascriptExports,
|
||||
},
|
||||
utils::StringifyJs,
|
||||
EcmascriptModuleAssetVc,
|
||||
EcmascriptModuleAsset,
|
||||
},
|
||||
};
|
||||
|
||||
use super::ecmascript_client_reference_module::EcmascriptClientReferenceModuleVc;
|
||||
use super::ecmascript_client_reference_module::EcmascriptClientReferenceModule;
|
||||
|
||||
/// A [`EcmascriptClientReferenceProxyModule`] is used in RSC to represent
|
||||
/// a client or SSR asset.
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub struct EcmascriptClientReferenceProxyModule {
|
||||
server_module_ident: AssetIdentVc,
|
||||
server_asset_context: AssetContextVc,
|
||||
client_module: EcmascriptChunkPlaceableVc,
|
||||
ssr_module: EcmascriptChunkPlaceableVc,
|
||||
server_module_ident: Vc<AssetIdent>,
|
||||
server_asset_context: Vc<Box<dyn AssetContext>>,
|
||||
client_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
ssr_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl EcmascriptClientReferenceProxyModuleVc {
|
||||
impl EcmascriptClientReferenceProxyModule {
|
||||
/// Create a new [`EcmascriptClientReferenceProxyModule`].
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -54,11 +52,11 @@ impl EcmascriptClientReferenceProxyModuleVc {
|
|||
/// * `ssr_module` - The SSR module.
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(
|
||||
server_module_ident: AssetIdentVc,
|
||||
server_asset_context: AssetContextVc,
|
||||
client_module: EcmascriptChunkPlaceableVc,
|
||||
ssr_module: EcmascriptChunkPlaceableVc,
|
||||
) -> EcmascriptClientReferenceProxyModuleVc {
|
||||
server_module_ident: Vc<AssetIdent>,
|
||||
server_asset_context: Vc<Box<dyn AssetContext>>,
|
||||
client_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
ssr_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
) -> Vc<EcmascriptClientReferenceProxyModule> {
|
||||
EcmascriptClientReferenceProxyModule {
|
||||
server_module_ident,
|
||||
server_asset_context,
|
||||
|
@ -69,7 +67,7 @@ impl EcmascriptClientReferenceProxyModuleVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn proxy_module_asset(self) -> Result<EcmascriptModuleAssetVc> {
|
||||
async fn proxy_module_asset(self: Vc<Self>) -> Result<Vc<EcmascriptModuleAsset>> {
|
||||
let this = self.await?;
|
||||
let mut code = CodeBuilder::default();
|
||||
|
||||
|
@ -96,18 +94,21 @@ impl EcmascriptClientReferenceProxyModuleVc {
|
|||
|
||||
let code = code.build();
|
||||
let proxy_module_asset_content =
|
||||
AssetContentVc::from(File::from(code.source_code().clone()));
|
||||
AssetContent::file(File::from(code.source_code().clone()).into());
|
||||
|
||||
let proxy_source = VirtualSourceVc::new(
|
||||
this.server_module_ident.path().join("proxy.ts"),
|
||||
let proxy_source = VirtualSource::new(
|
||||
this.server_module_ident.path().join("proxy.ts".to_string()),
|
||||
proxy_module_asset_content,
|
||||
);
|
||||
|
||||
let proxy_module = this
|
||||
.server_asset_context
|
||||
.process(proxy_source.into(), Value::new(ReferenceType::Undefined));
|
||||
let proxy_module = this.server_asset_context.process(
|
||||
Vc::upcast(proxy_source),
|
||||
Value::new(ReferenceType::Undefined),
|
||||
);
|
||||
|
||||
let Some(proxy_module) = EcmascriptModuleAssetVc::resolve_from(&proxy_module).await? else {
|
||||
let Some(proxy_module) =
|
||||
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(proxy_module).await?
|
||||
else {
|
||||
bail!("proxy asset is not an ecmascript module");
|
||||
};
|
||||
|
||||
|
@ -118,48 +119,42 @@ impl EcmascriptClientReferenceProxyModuleVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Asset for EcmascriptClientReferenceProxyModule {
|
||||
#[turbo_tasks::function]
|
||||
fn ident(&self) -> AssetIdentVc {
|
||||
fn ident(&self) -> Vc<AssetIdent> {
|
||||
self.server_module_ident
|
||||
.with_modifier(client_proxy_modifier())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn content(&self) -> Result<AssetContentVc> {
|
||||
fn content(&self) -> Result<Vc<AssetContent>> {
|
||||
bail!("proxy module asset has no content")
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn references(
|
||||
self_vc: EcmascriptClientReferenceProxyModuleVc,
|
||||
) -> Result<AssetReferencesVc> {
|
||||
async fn references(self: Vc<Self>) -> Result<Vc<AssetReferences>> {
|
||||
let EcmascriptClientReferenceProxyModule {
|
||||
server_module_ident,
|
||||
server_asset_context: _,
|
||||
client_module,
|
||||
ssr_module,
|
||||
} = &*self_vc.await?;
|
||||
} = &*self.await?;
|
||||
|
||||
let references: Vec<_> = self_vc
|
||||
let references: Vec<_> = self
|
||||
.proxy_module_asset()
|
||||
.references()
|
||||
.await?
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(once(
|
||||
SingleAssetReferenceVc::new(
|
||||
EcmascriptClientReferenceModuleVc::new(
|
||||
*server_module_ident,
|
||||
*client_module,
|
||||
*ssr_module,
|
||||
)
|
||||
.into(),
|
||||
client_reference_description(),
|
||||
)
|
||||
.into(),
|
||||
))
|
||||
.chain(once(Vc::upcast(SingleAssetReference::new(
|
||||
Vc::upcast(EcmascriptClientReferenceModule::new(
|
||||
*server_module_ident,
|
||||
*client_module,
|
||||
*ssr_module,
|
||||
)),
|
||||
client_reference_description(),
|
||||
))))
|
||||
.collect();
|
||||
|
||||
Ok(AssetReferencesVc::cell(references))
|
||||
Ok(Vc::cell(references))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,16 +165,15 @@ impl Module for EcmascriptClientReferenceProxyModule {}
|
|||
impl ChunkableModule for EcmascriptClientReferenceProxyModule {
|
||||
#[turbo_tasks::function]
|
||||
fn as_chunk(
|
||||
self_vc: EcmascriptClientReferenceProxyModuleVc,
|
||||
context: ChunkingContextVc,
|
||||
self: Vc<Self>,
|
||||
context: Vc<Box<dyn ChunkingContext>>,
|
||||
availability_info: Value<AvailabilityInfo>,
|
||||
) -> ChunkVc {
|
||||
EcmascriptChunkVc::new(
|
||||
) -> Vc<Box<dyn Chunk>> {
|
||||
Vc::upcast(EcmascriptChunk::new(
|
||||
context,
|
||||
self_vc.as_ecmascript_chunk_placeable(),
|
||||
Vc::upcast(self),
|
||||
availability_info,
|
||||
)
|
||||
.into()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,56 +181,57 @@ impl ChunkableModule for EcmascriptClientReferenceProxyModule {
|
|||
impl EcmascriptChunkPlaceable for EcmascriptClientReferenceProxyModule {
|
||||
#[turbo_tasks::function]
|
||||
fn as_chunk_item(
|
||||
self_vc: EcmascriptClientReferenceProxyModuleVc,
|
||||
chunking_context: EcmascriptChunkingContextVc,
|
||||
) -> EcmascriptChunkItemVc {
|
||||
ProxyModuleChunkItem {
|
||||
client_proxy_asset: self_vc,
|
||||
inner_proxy_module_chunk_item: self_vc
|
||||
.proxy_module_asset()
|
||||
.as_chunk_item(chunking_context),
|
||||
chunking_context,
|
||||
}
|
||||
.cell()
|
||||
.into()
|
||||
self: Vc<Self>,
|
||||
chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
) -> Vc<Box<dyn EcmascriptChunkItem>> {
|
||||
Vc::upcast(
|
||||
ProxyModuleChunkItem {
|
||||
client_proxy_asset: self,
|
||||
inner_proxy_module_chunk_item: self
|
||||
.proxy_module_asset()
|
||||
.as_chunk_item(chunking_context),
|
||||
chunking_context,
|
||||
}
|
||||
.cell(),
|
||||
)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn get_exports(self_vc: EcmascriptClientReferenceProxyModuleVc) -> EcmascriptExportsVc {
|
||||
self_vc.proxy_module_asset().get_exports()
|
||||
fn get_exports(self: Vc<Self>) -> Vc<EcmascriptExports> {
|
||||
self.proxy_module_asset().get_exports()
|
||||
}
|
||||
}
|
||||
|
||||
/// This wrapper only exists to overwrite the `asset_ident` method of the
|
||||
/// wrapped [`EcmascriptChunkItemVc`]. Otherwise, the asset ident of the
|
||||
/// chunk item would not be the same as the asset ident of the
|
||||
/// [`EcmascriptClientReferenceProxyModuleVc`].
|
||||
/// wrapped [`Vc<Box<dyn EcmascriptChunkItem>>`]. Otherwise, the asset ident of
|
||||
/// the chunk item would not be the same as the asset ident of the
|
||||
/// [`Vc<EcmascriptClientReferenceProxyModule>`].
|
||||
#[turbo_tasks::value]
|
||||
struct ProxyModuleChunkItem {
|
||||
client_proxy_asset: EcmascriptClientReferenceProxyModuleVc,
|
||||
inner_proxy_module_chunk_item: EcmascriptChunkItemVc,
|
||||
chunking_context: EcmascriptChunkingContextVc,
|
||||
client_proxy_asset: Vc<EcmascriptClientReferenceProxyModule>,
|
||||
inner_proxy_module_chunk_item: Vc<Box<dyn EcmascriptChunkItem>>,
|
||||
chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn client_proxy_modifier() -> StringVc {
|
||||
StringVc::cell("client proxy".to_string())
|
||||
fn client_proxy_modifier() -> Vc<String> {
|
||||
Vc::cell("client proxy".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn client_reference_description() -> StringVc {
|
||||
StringVc::cell("client references".to_string())
|
||||
fn client_reference_description() -> Vc<String> {
|
||||
Vc::cell("client references".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ChunkItem for ProxyModuleChunkItem {
|
||||
#[turbo_tasks::function]
|
||||
async fn asset_ident(&self) -> AssetIdentVc {
|
||||
async fn asset_ident(&self) -> Vc<AssetIdent> {
|
||||
self.client_proxy_asset.ident()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn references(&self) -> AssetReferencesVc {
|
||||
fn references(&self) -> Vc<AssetReferences> {
|
||||
self.client_proxy_asset.references()
|
||||
}
|
||||
}
|
||||
|
@ -244,7 +239,7 @@ impl ChunkItem for ProxyModuleChunkItem {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl EcmascriptChunkItem for ProxyModuleChunkItem {
|
||||
#[turbo_tasks::function]
|
||||
fn content(&self) -> EcmascriptChunkItemContentVc {
|
||||
fn content(&self) -> Vc<EcmascriptChunkItemContent> {
|
||||
self.inner_proxy_module_chunk_item.content()
|
||||
}
|
||||
|
||||
|
@ -252,13 +247,13 @@ impl EcmascriptChunkItem for ProxyModuleChunkItem {
|
|||
fn content_with_availability_info(
|
||||
&self,
|
||||
availability_info: Value<AvailabilityInfo>,
|
||||
) -> EcmascriptChunkItemContentVc {
|
||||
) -> Vc<EcmascriptChunkItemContent> {
|
||||
self.inner_proxy_module_chunk_item
|
||||
.content_with_availability_info(availability_info)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn chunking_context(&self) -> EcmascriptChunkingContextVc {
|
||||
fn chunking_context(&self) -> Vc<Box<dyn EcmascriptChunkingContext>> {
|
||||
self.inner_proxy_module_chunk_item.chunking_context()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::Value;
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
asset::Asset,
|
||||
module::ModuleVc,
|
||||
module::Module,
|
||||
reference_type::{EntryReferenceSubType, ReferenceType},
|
||||
source::SourceVc,
|
||||
source::Source,
|
||||
},
|
||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
||||
ecmascript::chunk::EcmascriptChunkPlaceable,
|
||||
turbopack::{
|
||||
transition::{ContextTransitionVc, Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
transition::{ContextTransition, Transition},
|
||||
ModuleAssetContext,
|
||||
},
|
||||
};
|
||||
|
||||
use super::ecmascript_client_reference_proxy_module::EcmascriptClientReferenceProxyModuleVc;
|
||||
use super::ecmascript_client_reference_proxy_module::EcmascriptClientReferenceProxyModule;
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextEcmascriptClientReferenceTransition {
|
||||
client_transition: ContextTransitionVc,
|
||||
ssr_transition: ContextTransitionVc,
|
||||
client_transition: Vc<ContextTransition>,
|
||||
ssr_transition: Vc<ContextTransition>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextEcmascriptClientReferenceTransitionVc {
|
||||
impl NextEcmascriptClientReferenceTransition {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(
|
||||
client_transition: ContextTransitionVc,
|
||||
ssr_transition: ContextTransitionVc,
|
||||
) -> Self {
|
||||
client_transition: Vc<ContextTransition>,
|
||||
ssr_transition: Vc<ContextTransition>,
|
||||
) -> Vc<Self> {
|
||||
NextEcmascriptClientReferenceTransition {
|
||||
client_transition,
|
||||
ssr_transition,
|
||||
|
@ -42,10 +42,10 @@ impl Transition for NextEcmascriptClientReferenceTransition {
|
|||
#[turbo_tasks::function]
|
||||
async fn process(
|
||||
&self,
|
||||
source: SourceVc,
|
||||
context: ModuleAssetContextVc,
|
||||
source: Vc<Box<dyn Source>>,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
_reference_type: Value<ReferenceType>,
|
||||
) -> Result<ModuleVc> {
|
||||
) -> Result<Vc<Box<dyn Module>>> {
|
||||
let client_module = self.client_transition.process(
|
||||
source,
|
||||
context,
|
||||
|
@ -62,31 +62,33 @@ impl Transition for NextEcmascriptClientReferenceTransition {
|
|||
)),
|
||||
);
|
||||
|
||||
let Some(client_module) = EcmascriptChunkPlaceableVc::resolve_from(&client_module).await?
|
||||
let Some(client_module) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(client_module).await?
|
||||
else {
|
||||
bail!("client asset is not ecmascript chunk placeable");
|
||||
};
|
||||
|
||||
let Some(ssr_module) = EcmascriptChunkPlaceableVc::resolve_from(&ssr_module).await? else {
|
||||
let Some(ssr_module) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(ssr_module).await?
|
||||
else {
|
||||
bail!("SSR asset is not ecmascript chunk placeable");
|
||||
};
|
||||
|
||||
// TODO(alexkirsz) This is necessary to remove the transition currently set on
|
||||
// the context.
|
||||
let context = context.await?;
|
||||
let server_context = ModuleAssetContextVc::new(
|
||||
let server_context = ModuleAssetContext::new(
|
||||
context.transitions,
|
||||
context.compile_time_info,
|
||||
context.module_options_context,
|
||||
context.resolve_options_context,
|
||||
);
|
||||
|
||||
Ok(EcmascriptClientReferenceProxyModuleVc::new(
|
||||
Ok(Vc::upcast(EcmascriptClientReferenceProxyModule::new(
|
||||
source.ident(),
|
||||
server_context.into(),
|
||||
Vc::upcast(server_context),
|
||||
client_module,
|
||||
ssr_module,
|
||||
)
|
||||
.into())
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,9 @@ pub(crate) mod css_client_reference;
|
|||
pub(crate) mod ecmascript_client_reference;
|
||||
pub(crate) mod visit_client_reference;
|
||||
|
||||
pub use css_client_reference::css_client_reference_module::CssClientReferenceModuleVc;
|
||||
pub use css_client_reference::css_client_reference_module::CssClientReferenceModule;
|
||||
pub use ecmascript_client_reference::{
|
||||
ecmascript_client_reference_module::EcmascriptClientReferenceModuleVc,
|
||||
ecmascript_client_reference_transition::NextEcmascriptClientReferenceTransitionVc,
|
||||
};
|
||||
pub use visit_client_reference::{
|
||||
ClientReference, ClientReferenceType, ClientReferencesByEntry, ClientReferencesByEntryVc,
|
||||
ecmascript_client_reference_module::EcmascriptClientReferenceModule,
|
||||
ecmascript_client_reference_transition::NextEcmascriptClientReferenceTransition,
|
||||
};
|
||||
pub use visit_client_reference::{ClientReference, ClientReferenceType, ClientReferencesByEntry};
|
||||
|
|
|
@ -7,29 +7,29 @@ use turbo_tasks::{
|
|||
debug::ValueDebugFormat,
|
||||
graph::{AdjacencyMap, GraphTraversal, Visit, VisitControlFlow},
|
||||
trace::TraceRawVcs,
|
||||
TryJoinIterExt,
|
||||
TryJoinIterExt, Vc,
|
||||
};
|
||||
use turbopack_binding::turbopack::core::{
|
||||
asset::{Asset, AssetVc, AssetsVc},
|
||||
asset::{Asset, Assets},
|
||||
reference::AssetReference,
|
||||
};
|
||||
|
||||
use super::{
|
||||
css_client_reference::css_client_reference_module::CssClientReferenceModuleVc,
|
||||
ecmascript_client_reference::ecmascript_client_reference_module::EcmascriptClientReferenceModuleVc,
|
||||
css_client_reference::css_client_reference_module::CssClientReferenceModule,
|
||||
ecmascript_client_reference::ecmascript_client_reference_module::EcmascriptClientReferenceModule,
|
||||
};
|
||||
use crate::next_server_component::server_component_module::NextServerComponentModuleVc;
|
||||
use crate::next_server_component::server_component_module::NextServerComponentModule;
|
||||
|
||||
#[derive(
|
||||
Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ValueDebugFormat, TraceRawVcs,
|
||||
)]
|
||||
pub struct ClientReference {
|
||||
server_component: Option<NextServerComponentModuleVc>,
|
||||
server_component: Option<Vc<NextServerComponentModule>>,
|
||||
ty: ClientReferenceType,
|
||||
}
|
||||
|
||||
impl ClientReference {
|
||||
pub fn server_component(&self) -> Option<&NextServerComponentModuleVc> {
|
||||
pub fn server_component(&self) -> Option<&Vc<NextServerComponentModule>> {
|
||||
self.server_component.as_ref()
|
||||
}
|
||||
|
||||
|
@ -42,17 +42,17 @@ impl ClientReference {
|
|||
Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ValueDebugFormat, TraceRawVcs,
|
||||
)]
|
||||
pub enum ClientReferenceType {
|
||||
EcmascriptClientReference(EcmascriptClientReferenceModuleVc),
|
||||
CssClientReference(CssClientReferenceModuleVc),
|
||||
EcmascriptClientReference(Vc<EcmascriptClientReferenceModule>),
|
||||
CssClientReference(Vc<CssClientReferenceModule>),
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub struct ClientReferencesByEntry(IndexMap<AssetVc, Vec<ClientReference>>);
|
||||
pub struct ClientReferencesByEntry(IndexMap<Vc<Box<dyn Asset>>, Vec<ClientReference>>);
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ClientReferencesByEntryVc {
|
||||
impl ClientReferencesByEntry {
|
||||
#[turbo_tasks::function]
|
||||
pub async fn new(entries: AssetsVc) -> Result<ClientReferencesByEntryVc> {
|
||||
pub async fn new(entries: Vc<Assets>) -> Result<Vc<ClientReferencesByEntry>> {
|
||||
let entries = entries.await?;
|
||||
|
||||
let graph = AdjacencyMap::new()
|
||||
|
@ -95,7 +95,7 @@ impl ClientReferencesByEntryVc {
|
|||
})
|
||||
.collect();
|
||||
|
||||
Ok(ClientReferencesByEntryVc::cell(client_references))
|
||||
Ok(Vc::cell(client_references))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,14 +103,14 @@ struct VisitClientReference;
|
|||
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
struct VisitClientReferenceNode {
|
||||
server_component: Option<NextServerComponentModuleVc>,
|
||||
server_component: Option<Vc<NextServerComponentModule>>,
|
||||
ty: VisitClientReferenceNodeType,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
enum VisitClientReferenceNodeType {
|
||||
ClientReference(ClientReference),
|
||||
Internal(AssetVc),
|
||||
Internal(Vc<Box<dyn Asset>>),
|
||||
}
|
||||
|
||||
impl Visit<VisitClientReferenceNode> for VisitClientReference {
|
||||
|
@ -149,7 +149,8 @@ impl Visit<VisitClientReferenceNode> for VisitClientReference {
|
|||
|
||||
let referenced_assets = referenced_assets.map(|asset| async move {
|
||||
if let Some(client_reference_asset) =
|
||||
EcmascriptClientReferenceModuleVc::resolve_from(asset).await?
|
||||
Vc::try_resolve_downcast_type::<EcmascriptClientReferenceModule>(asset)
|
||||
.await?
|
||||
{
|
||||
return Ok(VisitClientReferenceNode {
|
||||
server_component: node.server_component,
|
||||
|
@ -165,7 +166,7 @@ impl Visit<VisitClientReferenceNode> for VisitClientReference {
|
|||
}
|
||||
|
||||
if let Some(css_client_reference_asset) =
|
||||
CssClientReferenceModuleVc::resolve_from(asset).await?
|
||||
Vc::try_resolve_downcast_type::<CssClientReferenceModule>(asset).await?
|
||||
{
|
||||
return Ok(VisitClientReferenceNode {
|
||||
server_component: node.server_component,
|
||||
|
@ -181,7 +182,8 @@ impl Visit<VisitClientReferenceNode> for VisitClientReference {
|
|||
}
|
||||
|
||||
if let Some(server_component_asset) =
|
||||
NextServerComponentModuleVc::resolve_from(asset).await?
|
||||
Vc::try_resolve_downcast_type::<NextServerComponentModule>(asset)
|
||||
.await?
|
||||
{
|
||||
return Ok(VisitClientReferenceNode {
|
||||
server_component: Some(server_component_asset),
|
||||
|
|
|
@ -2,28 +2,24 @@ use anyhow::{Context, Result};
|
|||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
use turbo_tasks::{
|
||||
primitives::{BoolVc, JsonValueVc, StringVc, StringsVc},
|
||||
trace::TraceRawVcs,
|
||||
CompletionVc, Value,
|
||||
};
|
||||
use turbo_tasks::{trace::TraceRawVcs, Completion, Value, Vc};
|
||||
use turbo_tasks_fs::json::parse_json_with_source_context;
|
||||
use turbopack_binding::{
|
||||
turbo::{tasks_env::EnvMapVc, tasks_fs::FileSystemPathVc},
|
||||
turbo::{tasks_env::EnvMap, tasks_fs::FileSystemPath},
|
||||
turbopack::{
|
||||
core::{
|
||||
asset::Asset,
|
||||
changed::any_content_changed,
|
||||
chunk::ChunkingContext,
|
||||
context::AssetContext,
|
||||
file_source::FileSourceVc,
|
||||
ident::AssetIdentVc,
|
||||
issue::{Issue, IssueContextExt, IssueSeverity, IssueSeverityVc, IssueVc},
|
||||
reference_type::{EntryReferenceSubType, InnerAssetsVc, ReferenceType},
|
||||
file_source::FileSource,
|
||||
ident::AssetIdent,
|
||||
issue::{Issue, IssueContextExt, IssueExt, IssueSeverity},
|
||||
reference_type::{EntryReferenceSubType, InnerAssets, ReferenceType},
|
||||
resolve::{
|
||||
find_context_file,
|
||||
options::{ImportMap, ImportMapping},
|
||||
FindContextFileResult, ResolveAliasMap, ResolveAliasMapVc,
|
||||
FindContextFileResult, ResolveAliasMap,
|
||||
},
|
||||
},
|
||||
ecmascript_plugin::transform::{
|
||||
|
@ -33,12 +29,12 @@ use turbopack_binding::{
|
|||
node::{
|
||||
debug::should_debug,
|
||||
evaluate::evaluate,
|
||||
execution_context::{ExecutionContext, ExecutionContextVc},
|
||||
transforms::webpack::{WebpackLoaderItem, WebpackLoaderItemsVc},
|
||||
execution_context::ExecutionContext,
|
||||
transforms::webpack::{WebpackLoaderItem, WebpackLoaderItems},
|
||||
},
|
||||
turbopack::{
|
||||
evaluate_context::node_evaluate_asset_context,
|
||||
module_options::{LoaderRuleItem, OptionWebpackRulesVc, WebpackRulesVc},
|
||||
module_options::{LoaderRuleItem, OptionWebpackRules},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -54,8 +50,8 @@ struct NextConfigAndCustomRoutesRaw {
|
|||
|
||||
#[turbo_tasks::value]
|
||||
struct NextConfigAndCustomRoutes {
|
||||
config: NextConfigVc,
|
||||
custom_routes: CustomRoutesVc,
|
||||
config: Vc<NextConfig>,
|
||||
custom_routes: Vc<CustomRoutes>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||
|
@ -70,7 +66,7 @@ struct CustomRoutesRaw {
|
|||
|
||||
#[turbo_tasks::value]
|
||||
struct CustomRoutes {
|
||||
rewrites: RewritesVc,
|
||||
rewrites: Vc<Rewrites>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(serialization = "custom", eq = "manual")]
|
||||
|
@ -510,17 +506,17 @@ pub enum RemoveConsoleConfig {
|
|||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextConfigVc {
|
||||
impl NextConfig {
|
||||
#[turbo_tasks::function]
|
||||
pub fn from_string(s: String) -> Result<Self> {
|
||||
pub fn from_string(s: String) -> Result<Vc<Self>> {
|
||||
let config: NextConfig = serde_json::from_str(&s)
|
||||
.with_context(|| format!("failed to parse next.config.js: {}", s))?;
|
||||
Ok(config.cell())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn server_component_externals(self) -> Result<StringsVc> {
|
||||
Ok(StringsVc::cell(
|
||||
pub async fn server_component_externals(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
|
||||
Ok(Vc::cell(
|
||||
self.await?
|
||||
.experimental
|
||||
.server_components_external_packages
|
||||
|
@ -531,8 +527,8 @@ impl NextConfigVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn app_dir(self) -> Result<BoolVc> {
|
||||
Ok(BoolVc::cell(
|
||||
pub async fn app_dir(self: Vc<Self>) -> Result<Vc<bool>> {
|
||||
Ok(Vc::cell(
|
||||
self.await?
|
||||
.experimental
|
||||
.app_dir
|
||||
|
@ -543,7 +539,7 @@ impl NextConfigVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn env(self) -> Result<EnvMapVc> {
|
||||
pub async fn env(self: Vc<Self>) -> Result<Vc<EnvMap>> {
|
||||
// The value expected for env is Record<String, String>, but config itself
|
||||
// allows arbitary object (https://github.com/vercel/next.js/blob/25ba8a74b7544dfb6b30d1b67c47b9cb5360cb4e/packages/next/src/server/config-schema.ts#L203)
|
||||
// then stringifies it. We do the interop here as well.
|
||||
|
@ -564,28 +560,28 @@ impl NextConfigVc {
|
|||
})
|
||||
.collect();
|
||||
|
||||
Ok(EnvMapVc::cell(env))
|
||||
Ok(Vc::cell(env))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn image_config(self) -> Result<ImageConfigVc> {
|
||||
pub async fn image_config(self: Vc<Self>) -> Result<Vc<ImageConfig>> {
|
||||
Ok(self.await?.images.clone().cell())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn page_extensions(self) -> Result<StringsVc> {
|
||||
Ok(StringsVc::cell(self.await?.page_extensions.clone()))
|
||||
pub async fn page_extensions(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
|
||||
Ok(Vc::cell(self.await?.page_extensions.clone()))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn transpile_packages(self) -> Result<StringsVc> {
|
||||
Ok(StringsVc::cell(
|
||||
pub async fn transpile_packages(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
|
||||
Ok(Vc::cell(
|
||||
self.await?.transpile_packages.clone().unwrap_or_default(),
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn webpack_rules(self) -> Result<OptionWebpackRulesVc> {
|
||||
pub async fn webpack_rules(self: Vc<Self>) -> Result<Vc<OptionWebpackRules>> {
|
||||
let this = self.await?;
|
||||
let Some(turbo_rules) = this
|
||||
.experimental
|
||||
|
@ -593,15 +589,15 @@ impl NextConfigVc {
|
|||
.as_ref()
|
||||
.and_then(|t| t.rules.as_ref())
|
||||
else {
|
||||
return Ok(OptionWebpackRulesVc::cell(None));
|
||||
return Ok(Vc::cell(None));
|
||||
};
|
||||
if turbo_rules.is_empty() {
|
||||
return Ok(OptionWebpackRulesVc::cell(None));
|
||||
return Ok(Vc::cell(None));
|
||||
}
|
||||
let mut rules = IndexMap::new();
|
||||
for (ext, rule) in turbo_rules {
|
||||
fn transform_loaders(loaders: &[LoaderItem]) -> WebpackLoaderItemsVc {
|
||||
WebpackLoaderItemsVc::cell(
|
||||
fn transform_loaders(loaders: &[LoaderItem]) -> Vc<WebpackLoaderItems> {
|
||||
Vc::cell(
|
||||
loaders
|
||||
.iter()
|
||||
.map(|item| match item {
|
||||
|
@ -627,13 +623,11 @@ impl NextConfigVc {
|
|||
|
||||
rules.insert(ext.clone(), rule);
|
||||
}
|
||||
Ok(OptionWebpackRulesVc::cell(Some(WebpackRulesVc::cell(
|
||||
rules,
|
||||
))))
|
||||
Ok(Vc::cell(Some(Vc::cell(rules))))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn resolve_alias_options(self) -> Result<ResolveAliasMapVc> {
|
||||
pub async fn resolve_alias_options(self: Vc<Self>) -> Result<Vc<ResolveAliasMap>> {
|
||||
let this = self.await?;
|
||||
let Some(resolve_alias) = this
|
||||
.experimental
|
||||
|
@ -641,29 +635,27 @@ impl NextConfigVc {
|
|||
.as_ref()
|
||||
.and_then(|t| t.resolve_alias.as_ref())
|
||||
else {
|
||||
return Ok(ResolveAliasMapVc::cell(ResolveAliasMap::default()));
|
||||
return Ok(ResolveAliasMap::cell(ResolveAliasMap::default()));
|
||||
};
|
||||
let alias_map: ResolveAliasMap = resolve_alias.try_into()?;
|
||||
Ok(alias_map.cell())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn mdx_rs(self) -> Result<BoolVc> {
|
||||
Ok(BoolVc::cell(
|
||||
self.await?.experimental.mdx_rs.unwrap_or(false),
|
||||
))
|
||||
pub async fn mdx_rs(self: Vc<Self>) -> Result<Vc<bool>> {
|
||||
Ok(Vc::cell(self.await?.experimental.mdx_rs.unwrap_or(false)))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn sass_config(self) -> Result<JsonValueVc> {
|
||||
Ok(JsonValueVc::cell(
|
||||
pub async fn sass_config(self: Vc<Self>) -> Result<Vc<JsonValue>> {
|
||||
Ok(Vc::cell(
|
||||
self.await?.sass_options.clone().unwrap_or_default(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn next_configs() -> StringsVc {
|
||||
StringsVc::cell(
|
||||
fn next_configs() -> Vc<Vec<String>> {
|
||||
Vc::cell(
|
||||
["next.config.mjs", "next.config.js"]
|
||||
.into_iter()
|
||||
.map(ToOwned::to_owned)
|
||||
|
@ -672,14 +664,14 @@ fn next_configs() -> StringsVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn load_next_config(execution_context: ExecutionContextVc) -> Result<NextConfigVc> {
|
||||
pub async fn load_next_config(execution_context: Vc<ExecutionContext>) -> Result<Vc<NextConfig>> {
|
||||
Ok(load_config_and_custom_routes(execution_context)
|
||||
.await?
|
||||
.config)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn load_rewrites(execution_context: ExecutionContextVc) -> Result<RewritesVc> {
|
||||
pub async fn load_rewrites(execution_context: Vc<ExecutionContext>) -> Result<Vc<Rewrites>> {
|
||||
Ok(load_config_and_custom_routes(execution_context)
|
||||
.await?
|
||||
.custom_routes
|
||||
|
@ -689,8 +681,8 @@ pub async fn load_rewrites(execution_context: ExecutionContextVc) -> Result<Rewr
|
|||
|
||||
#[turbo_tasks::function]
|
||||
async fn load_config_and_custom_routes(
|
||||
execution_context: ExecutionContextVc,
|
||||
) -> Result<NextConfigAndCustomRoutesVc> {
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
) -> Result<Vc<NextConfigAndCustomRoutes>> {
|
||||
let ExecutionContext { project_path, .. } = *execution_context.await?;
|
||||
let find_config_result = find_context_file(project_path, next_configs());
|
||||
let config_file = match &*find_config_result.await? {
|
||||
|
@ -705,9 +697,9 @@ async fn load_config_and_custom_routes(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
async fn load_next_config_and_custom_routes_internal(
|
||||
execution_context: ExecutionContextVc,
|
||||
config_file: Option<FileSystemPathVc>,
|
||||
) -> Result<NextConfigAndCustomRoutesVc> {
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
config_file: Option<Vc<FileSystemPath>>,
|
||||
) -> Result<Vc<NextConfigAndCustomRoutes>> {
|
||||
let ExecutionContext {
|
||||
project_path,
|
||||
chunking_context,
|
||||
|
@ -721,28 +713,28 @@ async fn load_next_config_and_custom_routes_internal(
|
|||
import_map.insert_wildcard_alias("styled-jsx/", ImportMapping::External(None).into());
|
||||
|
||||
let context = node_evaluate_asset_context(execution_context, Some(import_map.cell()), None);
|
||||
let config_asset = config_file.map(FileSourceVc::new);
|
||||
let config_asset = config_file.map(FileSource::new);
|
||||
|
||||
let config_changed = config_asset.map_or_else(CompletionVc::immutable, |config_asset| {
|
||||
let config_changed = config_asset.map_or_else(Completion::immutable, |config_asset| {
|
||||
// This invalidates the execution when anything referenced by the config file
|
||||
// changes
|
||||
let config_asset = context.process(
|
||||
config_asset.into(),
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::empty())),
|
||||
Vc::upcast(config_asset),
|
||||
Value::new(ReferenceType::Internal(InnerAssets::empty())),
|
||||
);
|
||||
any_content_changed(config_asset.into())
|
||||
any_content_changed(Vc::upcast(config_asset))
|
||||
});
|
||||
let load_next_config_asset = context.process(
|
||||
next_asset("entry/config/next.js"),
|
||||
next_asset("entry/config/next.js".to_string()),
|
||||
Value::new(ReferenceType::Entry(EntryReferenceSubType::Undefined)),
|
||||
);
|
||||
let config_value = evaluate(
|
||||
load_next_config_asset.into(),
|
||||
Vc::upcast(load_next_config_asset),
|
||||
project_path,
|
||||
env,
|
||||
config_asset.map_or_else(|| AssetIdentVc::from_path(project_path), |c| c.ident()),
|
||||
config_asset.map_or_else(|| AssetIdent::from_path(project_path), |c| c.ident()),
|
||||
context,
|
||||
chunking_context.with_layer("next_config"),
|
||||
chunking_context.with_layer("next_config".to_string()),
|
||||
None,
|
||||
vec![],
|
||||
config_changed,
|
||||
|
@ -778,13 +770,12 @@ async fn load_next_config_and_custom_routes_internal(
|
|||
path: config_file.unwrap_or(project_path),
|
||||
old_name: "experimental.turbo.loaders".to_string(),
|
||||
new_name: "experimental.turbo.rules".to_string(),
|
||||
description: "The new option is similar, but the key should be a glob instead of \
|
||||
an extension.
|
||||
Example: loaders: { \".mdx\": [\"mdx-loader\"] } -> rules: { \"*.mdx\": [\"mdx-loader\"] }"
|
||||
.to_string(),
|
||||
description: indoc::indoc! { r#"
|
||||
The new option is similar, but the key should be a glob instead of an extension.
|
||||
Example: loaders: { ".mdx": ["mdx-loader"] } -> rules: { "*.mdx": ["mdx-loader"] }"# }
|
||||
.to_string(),
|
||||
}
|
||||
.cell()
|
||||
.as_issue()
|
||||
.emit()
|
||||
}
|
||||
}
|
||||
|
@ -800,8 +791,8 @@ Example: loaders: { \".mdx\": [\"mdx-loader\"] } -> rules: { \"*.mdx\": [\"mdx-l
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn has_next_config(context: FileSystemPathVc) -> Result<BoolVc> {
|
||||
Ok(BoolVc::cell(!matches!(
|
||||
pub async fn has_next_config(context: Vc<FileSystemPath>) -> Result<Vc<bool>> {
|
||||
Ok(Vc::cell(!matches!(
|
||||
*find_context_file(context, next_configs()).await?,
|
||||
FindContextFileResult::NotFound(_)
|
||||
)))
|
||||
|
@ -809,7 +800,7 @@ pub async fn has_next_config(context: FileSystemPathVc) -> Result<BoolVc> {
|
|||
|
||||
#[turbo_tasks::value]
|
||||
struct OutdatedConfigIssue {
|
||||
path: FileSystemPathVc,
|
||||
path: Vc<FileSystemPath>,
|
||||
old_name: String,
|
||||
new_name: String,
|
||||
description: String,
|
||||
|
@ -818,30 +809,30 @@ struct OutdatedConfigIssue {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Issue for OutdatedConfigIssue {
|
||||
#[turbo_tasks::function]
|
||||
fn severity(&self) -> IssueSeverityVc {
|
||||
fn severity(&self) -> Vc<IssueSeverity> {
|
||||
IssueSeverity::Error.into()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn category(&self) -> StringVc {
|
||||
StringVc::cell("config".to_string())
|
||||
fn category(&self) -> Vc<String> {
|
||||
Vc::cell("config".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn context(&self) -> FileSystemPathVc {
|
||||
fn context(&self) -> Vc<FileSystemPath> {
|
||||
self.path
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn title(&self) -> StringVc {
|
||||
StringVc::cell(format!(
|
||||
fn title(&self) -> Vc<String> {
|
||||
Vc::cell(format!(
|
||||
"\"{}\" has been replaced by \"{}\"",
|
||||
self.old_name, self.new_name
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn description(&self) -> StringVc {
|
||||
StringVc::cell(self.description.to_string())
|
||||
fn description(&self) -> Vc<String> {
|
||||
Vc::cell(self.description.to_string())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::primitives::StringVc;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::core::{
|
||||
asset::{Asset, AssetContentVc, AssetVc},
|
||||
chunk::{ChunkableModule, ChunkableModuleVc, ChunkingContext, ChunkingContextVc},
|
||||
ident::AssetIdentVc,
|
||||
module::{Module, ModuleVc},
|
||||
output::OutputAssetsVc,
|
||||
reference::AssetReferencesVc,
|
||||
asset::{Asset, AssetContent},
|
||||
chunk::{ChunkableModule, ChunkingContext},
|
||||
ident::AssetIdent,
|
||||
module::Module,
|
||||
output::OutputAssets,
|
||||
reference::AssetReferences,
|
||||
};
|
||||
|
||||
/// A [`NextDynamicEntryModule`] is a marker asset used to indicate which
|
||||
/// dynamic assets should appear in the dynamic manifest.
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub struct NextDynamicEntryModule {
|
||||
pub client_entry_module: ModuleVc,
|
||||
pub client_entry_module: Vc<Box<dyn Module>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextDynamicEntryModuleVc {
|
||||
impl NextDynamicEntryModule {
|
||||
/// Create a new [`NextDynamicEntryModule`] from the given source CSS
|
||||
/// asset.
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(client_entry_module: ModuleVc) -> NextDynamicEntryModuleVc {
|
||||
pub fn new(client_entry_module: Vc<Box<dyn Module>>) -> Vc<NextDynamicEntryModule> {
|
||||
NextDynamicEntryModule {
|
||||
client_entry_module,
|
||||
}
|
||||
|
@ -30,13 +30,13 @@ impl NextDynamicEntryModuleVc {
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn client_chunks(
|
||||
self,
|
||||
client_chunking_context: ChunkingContextVc,
|
||||
) -> Result<OutputAssetsVc> {
|
||||
self: Vc<Self>,
|
||||
client_chunking_context: Vc<Box<dyn ChunkingContext>>,
|
||||
) -> Result<Vc<OutputAssets>> {
|
||||
let this = self.await?;
|
||||
|
||||
let Some(client_entry_module) =
|
||||
ChunkableModuleVc::resolve_from(this.client_entry_module).await?
|
||||
Vc::try_resolve_sidecast::<Box<dyn ChunkableModule>>(this.client_entry_module).await?
|
||||
else {
|
||||
bail!("dynamic client asset must be chunkable");
|
||||
};
|
||||
|
@ -47,28 +47,28 @@ impl NextDynamicEntryModuleVc {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn dynamic_modifier() -> StringVc {
|
||||
StringVc::cell("dynamic".to_string())
|
||||
fn dynamic_modifier() -> Vc<String> {
|
||||
Vc::cell("dynamic".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Asset for NextDynamicEntryModule {
|
||||
#[turbo_tasks::function]
|
||||
fn ident(&self) -> AssetIdentVc {
|
||||
fn ident(&self) -> Vc<AssetIdent> {
|
||||
self.client_entry_module
|
||||
.ident()
|
||||
.with_modifier(dynamic_modifier())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn content(&self) -> Result<AssetContentVc> {
|
||||
fn content(&self) -> Result<Vc<AssetContent>> {
|
||||
// The client reference asset only serves as a marker asset.
|
||||
bail!("NextDynamicEntryModule has no content")
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn references(_self_vc: NextDynamicEntryModuleVc) -> AssetReferencesVc {
|
||||
AssetReferencesVc::empty()
|
||||
fn references(self: Vc<Self>) -> Vc<AssetReferences> {
|
||||
AssetReferences::empty()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
use anyhow::Result;
|
||||
use turbo_tasks::Value;
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{module::ModuleVc, reference_type::ReferenceType, source::SourceVc},
|
||||
core::{module::Module, reference_type::ReferenceType, source::Source},
|
||||
turbopack::{
|
||||
transition::{ContextTransitionVc, Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
transition::{ContextTransition, Transition},
|
||||
ModuleAssetContext,
|
||||
},
|
||||
};
|
||||
|
||||
use super::NextDynamicEntryModuleVc;
|
||||
use super::NextDynamicEntryModule;
|
||||
|
||||
/// This transition is used to create the marker asset for a next/dynamic
|
||||
/// import. This will get picked up during module processing and will be used to
|
||||
/// create the dynamic entry, and the dynamic manifest entry.
|
||||
#[turbo_tasks::value]
|
||||
pub struct NextDynamicTransition {
|
||||
client_transition: ContextTransitionVc,
|
||||
client_transition: Vc<ContextTransition>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextDynamicTransitionVc {
|
||||
impl NextDynamicTransition {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(client_transition: ContextTransitionVc) -> Self {
|
||||
pub fn new(client_transition: Vc<ContextTransition>) -> Vc<Self> {
|
||||
NextDynamicTransition { client_transition }.cell()
|
||||
}
|
||||
}
|
||||
|
@ -31,14 +31,14 @@ impl Transition for NextDynamicTransition {
|
|||
#[turbo_tasks::function]
|
||||
async fn process(
|
||||
&self,
|
||||
source: SourceVc,
|
||||
context: ModuleAssetContextVc,
|
||||
source: Vc<Box<dyn Source>>,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
_reference_type: Value<ReferenceType>,
|
||||
) -> Result<ModuleVc> {
|
||||
) -> Result<Vc<Box<dyn Module>>> {
|
||||
let client_module =
|
||||
self.client_transition
|
||||
.process(source, context, Value::new(ReferenceType::Undefined));
|
||||
|
||||
Ok(NextDynamicEntryModuleVc::new(client_module).into())
|
||||
Ok(Vc::upcast(NextDynamicEntryModule::new(client_module)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,6 @@ pub(crate) mod dynamic_module;
|
|||
pub(crate) mod dynamic_transition;
|
||||
pub(crate) mod visit_dynamic;
|
||||
|
||||
pub use dynamic_module::NextDynamicEntryModuleVc;
|
||||
pub use dynamic_transition::NextDynamicTransitionVc;
|
||||
pub use visit_dynamic::NextDynamicEntriesVc;
|
||||
pub use dynamic_module::NextDynamicEntryModule;
|
||||
pub use dynamic_transition::NextDynamicTransition;
|
||||
pub use visit_dynamic::NextDynamicEntries;
|
||||
|
|
|
@ -3,22 +3,22 @@ use std::future::Future;
|
|||
use anyhow::Result;
|
||||
use turbo_tasks::{
|
||||
graph::{AdjacencyMap, GraphTraversal, Visit, VisitControlFlow},
|
||||
TryJoinIterExt,
|
||||
TryJoinIterExt, Vc,
|
||||
};
|
||||
use turbopack_binding::turbopack::core::{
|
||||
asset::{Asset, AssetVc, AssetsVc},
|
||||
asset::{Asset, Assets},
|
||||
reference::AssetReference,
|
||||
};
|
||||
|
||||
use super::NextDynamicEntryModuleVc;
|
||||
use super::NextDynamicEntryModule;
|
||||
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub struct NextDynamicEntries(Vec<NextDynamicEntryModuleVc>);
|
||||
pub struct NextDynamicEntries(Vec<Vc<NextDynamicEntryModule>>);
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextDynamicEntriesVc {
|
||||
impl NextDynamicEntries {
|
||||
#[turbo_tasks::function]
|
||||
pub async fn from_entries(entries: AssetsVc) -> Result<NextDynamicEntriesVc> {
|
||||
pub async fn from_entries(entries: Vc<Assets>) -> Result<Vc<NextDynamicEntries>> {
|
||||
let nodes: Vec<_> = AdjacencyMap::new()
|
||||
.skip_duplicates()
|
||||
.visit(
|
||||
|
@ -50,7 +50,7 @@ impl NextDynamicEntriesVc {
|
|||
}
|
||||
}
|
||||
|
||||
Ok(NextDynamicEntriesVc::cell(next_dynamics))
|
||||
Ok(Vc::cell(next_dynamics))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,8 +58,8 @@ struct VisitDynamic;
|
|||
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
enum VisitDynamicNode {
|
||||
Dynamic(NextDynamicEntryModuleVc),
|
||||
Internal(AssetVc),
|
||||
Dynamic(Vc<NextDynamicEntryModule>),
|
||||
Internal(Vc<Box<dyn Asset>>),
|
||||
}
|
||||
|
||||
impl Visit<VisitDynamicNode> for VisitDynamic {
|
||||
|
@ -77,7 +77,7 @@ impl Visit<VisitDynamicNode> for VisitDynamic {
|
|||
let node = node.clone();
|
||||
async move {
|
||||
let asset = match node {
|
||||
VisitDynamicNode::Dynamic(dynamic_asset) => dynamic_asset.into(),
|
||||
VisitDynamicNode::Dynamic(dynamic_asset) => Vc::upcast(dynamic_asset),
|
||||
VisitDynamicNode::Internal(asset) => asset,
|
||||
};
|
||||
|
||||
|
@ -97,7 +97,7 @@ impl Visit<VisitDynamicNode> for VisitDynamic {
|
|||
|
||||
let referenced_assets = referenced_assets.map(|asset| async move {
|
||||
if let Some(next_dynamic_asset) =
|
||||
NextDynamicEntryModuleVc::resolve_from(asset).await?
|
||||
Vc::try_resolve_downcast_type::<NextDynamicEntryModule>(asset).await?
|
||||
{
|
||||
return Ok(VisitDynamicNode::Dynamic(next_dynamic_asset));
|
||||
}
|
||||
|
|
|
@ -1,28 +1,25 @@
|
|||
use anyhow::Result;
|
||||
use turbo_tasks::Value;
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::FileSystemPathVc,
|
||||
turbo::tasks_fs::FileSystemPath,
|
||||
turbopack::{
|
||||
core::{
|
||||
compile_time_defines,
|
||||
compile_time_info::{
|
||||
CompileTimeDefines, CompileTimeDefinesVc, CompileTimeInfo, CompileTimeInfoVc,
|
||||
FreeVarReference, FreeVarReferencesVc,
|
||||
},
|
||||
environment::{
|
||||
EdgeWorkerEnvironment, EnvironmentVc, ExecutionEnvironment, ServerAddrVc,
|
||||
CompileTimeDefines, CompileTimeInfo, FreeVarReference, FreeVarReferences,
|
||||
},
|
||||
environment::{EdgeWorkerEnvironment, Environment, ExecutionEnvironment, ServerAddr},
|
||||
free_var_references,
|
||||
},
|
||||
node::execution_context::ExecutionContextVc,
|
||||
turbopack::resolve_options_context::{ResolveOptionsContext, ResolveOptionsContextVc},
|
||||
node::execution_context::ExecutionContext,
|
||||
turbopack::resolve_options_context::ResolveOptionsContext,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
mode::NextMode, next_config::NextConfigVc, next_import_map::get_next_edge_import_map,
|
||||
next_server::context::ServerContextType,
|
||||
next_shared::resolve::UnsupportedModulesResolvePluginVc, util::foreign_code_context_condition,
|
||||
mode::NextMode, next_config::NextConfig, next_import_map::get_next_edge_import_map,
|
||||
next_server::context::ServerContextType, next_shared::resolve::UnsupportedModulesResolvePlugin,
|
||||
util::foreign_code_context_condition,
|
||||
};
|
||||
|
||||
fn defines() -> CompileTimeDefines {
|
||||
|
@ -37,12 +34,12 @@ fn defines() -> CompileTimeDefines {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn next_edge_defines() -> CompileTimeDefinesVc {
|
||||
fn next_edge_defines() -> Vc<CompileTimeDefines> {
|
||||
defines().cell()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn next_edge_free_vars(project_path: FileSystemPathVc) -> FreeVarReferencesVc {
|
||||
fn next_edge_free_vars(project_path: Vc<FileSystemPath>) -> Vc<FreeVarReferences> {
|
||||
free_var_references!(
|
||||
..defines().into_iter(),
|
||||
Buffer = FreeVarReference::EcmaScriptModule {
|
||||
|
@ -61,10 +58,10 @@ fn next_edge_free_vars(project_path: FileSystemPathVc) -> FreeVarReferencesVc {
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub fn get_edge_compile_time_info(
|
||||
project_path: FileSystemPathVc,
|
||||
server_addr: ServerAddrVc,
|
||||
) -> CompileTimeInfoVc {
|
||||
CompileTimeInfo::builder(EnvironmentVc::new(Value::new(
|
||||
project_path: Vc<FileSystemPath>,
|
||||
server_addr: Vc<ServerAddr>,
|
||||
) -> Vc<CompileTimeInfo> {
|
||||
CompileTimeInfo::builder(Environment::new(Value::new(
|
||||
ExecutionEnvironment::EdgeWorker(EdgeWorkerEnvironment { server_addr }.into()),
|
||||
)))
|
||||
.defines(next_edge_defines())
|
||||
|
@ -74,12 +71,12 @@ pub fn get_edge_compile_time_info(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_edge_resolve_options_context(
|
||||
project_path: FileSystemPathVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
ty: Value<ServerContextType>,
|
||||
mode: NextMode,
|
||||
next_config: NextConfigVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
) -> Result<ResolveOptionsContextVc> {
|
||||
next_config: Vc<NextConfig>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
) -> Result<Vc<ResolveOptionsContext>> {
|
||||
let next_edge_import_map =
|
||||
get_next_edge_import_map(project_path, ty, mode, next_config, execution_context);
|
||||
|
||||
|
@ -94,7 +91,9 @@ pub async fn get_edge_resolve_options_context(
|
|||
import_map: Some(next_edge_import_map),
|
||||
module: true,
|
||||
browser: true,
|
||||
plugins: vec![UnsupportedModulesResolvePluginVc::new(project_path).into()],
|
||||
plugins: vec![Vc::upcast(UnsupportedModulesResolvePlugin::new(
|
||||
project_path,
|
||||
))],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
|
|
@ -1,24 +1,22 @@
|
|||
use anyhow::{bail, Result};
|
||||
use indexmap::indexmap;
|
||||
use turbo_tasks::Value;
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::FileSystemPathVc,
|
||||
turbo::tasks_fs::FileSystemPath,
|
||||
turbopack::{
|
||||
core::{
|
||||
chunk::{ChunkableModuleVc, ChunkingContextVc},
|
||||
compile_time_info::CompileTimeInfoVc,
|
||||
chunk::{ChunkableModule, ChunkingContext},
|
||||
compile_time_info::CompileTimeInfo,
|
||||
context::AssetContext,
|
||||
file_source::FileSourceVc,
|
||||
module::ModuleVc,
|
||||
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssetsVc, ReferenceType},
|
||||
source::SourceVc,
|
||||
file_source::FileSource,
|
||||
module::Module,
|
||||
reference_type::{EcmaScriptModulesReferenceSubType, ReferenceType},
|
||||
source::Source,
|
||||
},
|
||||
ecmascript::chunk_group_files_asset::ChunkGroupFilesAsset,
|
||||
turbopack::{
|
||||
module_options::ModuleOptionsContextVc,
|
||||
resolve_options_context::ResolveOptionsContextVc,
|
||||
transition::{Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
module_options::ModuleOptionsContext, resolve_options_context::ResolveOptionsContext,
|
||||
transition::Transition, ModuleAssetContext,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -32,12 +30,12 @@ use crate::embed_js::next_js_file_path;
|
|||
/// that for running them in the edge sandbox.
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextEdgePageTransition {
|
||||
pub edge_compile_time_info: CompileTimeInfoVc,
|
||||
pub edge_chunking_context: ChunkingContextVc,
|
||||
pub edge_module_options_context: Option<ModuleOptionsContextVc>,
|
||||
pub edge_resolve_options_context: ResolveOptionsContextVc,
|
||||
pub output_path: FileSystemPathVc,
|
||||
pub bootstrap_asset: SourceVc,
|
||||
pub edge_compile_time_info: Vc<CompileTimeInfo>,
|
||||
pub edge_chunking_context: Vc<Box<dyn ChunkingContext>>,
|
||||
pub edge_module_options_context: Option<Vc<ModuleOptionsContext>>,
|
||||
pub edge_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||
pub output_path: Vc<FileSystemPath>,
|
||||
pub bootstrap_asset: Vc<Box<dyn Source>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
|
@ -45,47 +43,48 @@ impl Transition for NextEdgePageTransition {
|
|||
#[turbo_tasks::function]
|
||||
fn process_compile_time_info(
|
||||
&self,
|
||||
_compile_time_info: CompileTimeInfoVc,
|
||||
) -> CompileTimeInfoVc {
|
||||
_compile_time_info: Vc<CompileTimeInfo>,
|
||||
) -> Vc<CompileTimeInfo> {
|
||||
self.edge_compile_time_info
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_module_options_context(
|
||||
&self,
|
||||
context: ModuleOptionsContextVc,
|
||||
) -> ModuleOptionsContextVc {
|
||||
context: Vc<ModuleOptionsContext>,
|
||||
) -> Vc<ModuleOptionsContext> {
|
||||
self.edge_module_options_context.unwrap_or(context)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_resolve_options_context(
|
||||
&self,
|
||||
_context: ResolveOptionsContextVc,
|
||||
) -> ResolveOptionsContextVc {
|
||||
_context: Vc<ResolveOptionsContext>,
|
||||
) -> Vc<ResolveOptionsContext> {
|
||||
self.edge_resolve_options_context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn process_module(
|
||||
&self,
|
||||
asset: ModuleVc,
|
||||
context: ModuleAssetContextVc,
|
||||
) -> Result<ModuleVc> {
|
||||
asset: Vc<Box<dyn Module>>,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
) -> Result<Vc<Box<dyn Module>>> {
|
||||
let module = context.process(
|
||||
self.bootstrap_asset,
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap! {
|
||||
"APP_ENTRY".to_string() => asset.into(),
|
||||
"APP_BOOTSTRAP".to_string() => context.with_transition("next-client").process(
|
||||
FileSourceVc::new(next_js_file_path("entry/app/hydrate.tsx")).into(),
|
||||
Value::new(ReferenceType::Internal(Vc::cell(indexmap! {
|
||||
"APP_ENTRY".to_string() => Vc::upcast(asset),
|
||||
"APP_BOOTSTRAP".to_string() => Vc::upcast(context.with_transition("next-client".to_string()).process(
|
||||
Vc::upcast(FileSource::new(next_js_file_path("entry/app/hydrate.tsx".to_string()))),
|
||||
Value::new(ReferenceType::EcmaScriptModules(
|
||||
EcmaScriptModulesReferenceSubType::Undefined,
|
||||
)),
|
||||
).into(),
|
||||
)),
|
||||
}))),
|
||||
);
|
||||
|
||||
let Some(module) = ChunkableModuleVc::resolve_from(module).await? else {
|
||||
let Some(module) = Vc::try_resolve_sidecast::<Box<dyn ChunkableModule>>(module).await?
|
||||
else {
|
||||
bail!("Internal module is not chunkable");
|
||||
};
|
||||
|
||||
|
@ -96,6 +95,6 @@ impl Transition for NextEdgePageTransition {
|
|||
runtime_entries: None,
|
||||
};
|
||||
|
||||
Ok(asset.cell().into())
|
||||
Ok(Vc::upcast(asset.cell()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,32 @@
|
|||
use anyhow::Result;
|
||||
use indexmap::indexmap;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::FileSystemPathVc,
|
||||
turbo::tasks_fs::FileSystemPath,
|
||||
turbopack::{
|
||||
core::{
|
||||
chunk::ChunkingContextVc, compile_time_info::CompileTimeInfoVc, module::ModuleVc,
|
||||
source::SourceVc,
|
||||
chunk::ChunkingContext, compile_time_info::CompileTimeInfo, module::Module,
|
||||
source::Source,
|
||||
},
|
||||
ecmascript::chunk_group_files_asset::ChunkGroupFilesAsset,
|
||||
turbopack::{
|
||||
module_options::ModuleOptionsContextVc,
|
||||
resolve_options_context::ResolveOptionsContextVc,
|
||||
transition::{Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
module_options::ModuleOptionsContext, resolve_options_context::ResolveOptionsContext,
|
||||
transition::Transition, ModuleAssetContext,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::bootstrap::{route_bootstrap, BootstrapConfigVc};
|
||||
use crate::bootstrap::route_bootstrap;
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextEdgeRouteTransition {
|
||||
pub edge_compile_time_info: CompileTimeInfoVc,
|
||||
pub edge_chunking_context: ChunkingContextVc,
|
||||
pub edge_module_options_context: Option<ModuleOptionsContextVc>,
|
||||
pub edge_resolve_options_context: ResolveOptionsContextVc,
|
||||
pub output_path: FileSystemPathVc,
|
||||
pub base_path: FileSystemPathVc,
|
||||
pub bootstrap_asset: SourceVc,
|
||||
pub edge_compile_time_info: Vc<CompileTimeInfo>,
|
||||
pub edge_chunking_context: Vc<Box<dyn ChunkingContext>>,
|
||||
pub edge_module_options_context: Option<Vc<ModuleOptionsContext>>,
|
||||
pub edge_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||
pub output_path: Vc<FileSystemPath>,
|
||||
pub base_path: Vc<FileSystemPath>,
|
||||
pub bootstrap_asset: Vc<Box<dyn Source>>,
|
||||
pub entry_name: String,
|
||||
}
|
||||
|
||||
|
@ -36,50 +35,50 @@ impl Transition for NextEdgeRouteTransition {
|
|||
#[turbo_tasks::function]
|
||||
fn process_compile_time_info(
|
||||
&self,
|
||||
_compile_time_info: CompileTimeInfoVc,
|
||||
) -> CompileTimeInfoVc {
|
||||
_compile_time_info: Vc<CompileTimeInfo>,
|
||||
) -> Vc<CompileTimeInfo> {
|
||||
self.edge_compile_time_info
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_module_options_context(
|
||||
&self,
|
||||
context: ModuleOptionsContextVc,
|
||||
) -> ModuleOptionsContextVc {
|
||||
context: Vc<ModuleOptionsContext>,
|
||||
) -> Vc<ModuleOptionsContext> {
|
||||
self.edge_module_options_context.unwrap_or(context)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn process_resolve_options_context(
|
||||
&self,
|
||||
_context: ResolveOptionsContextVc,
|
||||
) -> ResolveOptionsContextVc {
|
||||
_context: Vc<ResolveOptionsContext>,
|
||||
) -> Vc<ResolveOptionsContext> {
|
||||
self.edge_resolve_options_context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn process_module(
|
||||
&self,
|
||||
asset: ModuleVc,
|
||||
context: ModuleAssetContextVc,
|
||||
) -> Result<ModuleVc> {
|
||||
asset: Vc<Box<dyn Module>>,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
) -> Result<Vc<Box<dyn Module>>> {
|
||||
let new_asset = route_bootstrap(
|
||||
asset.into(),
|
||||
context.into(),
|
||||
Vc::upcast(asset),
|
||||
Vc::upcast(context),
|
||||
self.base_path,
|
||||
self.bootstrap_asset,
|
||||
BootstrapConfigVc::cell(indexmap! {
|
||||
Vc::cell(indexmap! {
|
||||
"NAME".to_string() => self.entry_name.clone(),
|
||||
}),
|
||||
);
|
||||
|
||||
let asset = ChunkGroupFilesAsset {
|
||||
module: new_asset.into(),
|
||||
module: Vc::upcast(new_asset),
|
||||
client_root: self.output_path,
|
||||
chunking_context: self.edge_chunking_context,
|
||||
runtime_entries: None,
|
||||
};
|
||||
|
||||
Ok(asset.cell().into())
|
||||
Ok(Vc::upcast(asset.cell()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turbopack_binding::turbo::tasks::{
|
||||
primitives::{StringVc, StringsVc},
|
||||
trace::TraceRawVcs,
|
||||
};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbo::tasks::trace::TraceRawVcs;
|
||||
|
||||
pub(crate) struct DefaultFallbackFont {
|
||||
pub name: String,
|
||||
|
@ -34,9 +31,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: StringVc,
|
||||
pub scoped_font_family: Vc<String>,
|
||||
/// The name of font locally, used in `src: local("{}")`
|
||||
pub local_font_family: StringVc,
|
||||
pub local_font_family: Vc<String>,
|
||||
pub adjustment: Option<FontAdjustment>,
|
||||
}
|
||||
|
||||
|
@ -45,17 +42,17 @@ pub(crate) struct AutomaticFontFallback {
|
|||
pub(crate) enum FontFallback {
|
||||
/// An automatically generated fallback font generated by next/font. May
|
||||
/// include an optional [[FontAdjustment]].
|
||||
Automatic(AutomaticFontFallbackVc),
|
||||
Automatic(Vc<AutomaticFontFallback>),
|
||||
/// There was an issue preparing the font fallback. Since resolving the
|
||||
/// font css cannot fail, proper Errors cannot be returned. Emit an issue,
|
||||
/// return this and omit fallback information instead.
|
||||
Error,
|
||||
/// A list of manually provided font names to use a fallback, as-is.
|
||||
Manual(StringsVc),
|
||||
Manual(Vc<Vec<String>>),
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub(crate) struct FontFallbacks(Vec<FontFallbackVc>);
|
||||
pub(crate) struct FontFallbacks(Vec<Vc<FontFallback>>);
|
||||
|
||||
/// An adjustment to be made to a fallback font to approximate the geometry of
|
||||
/// the main webfont. Rendered as e.g. `ascent-override: 56.8%;` in the
|
||||
|
|
|
@ -4,18 +4,18 @@ use anyhow::{Context, Result};
|
|||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turbo_tasks::{
|
||||
primitives::{StringVc, StringsVc, U32Vc},
|
||||
trace::TraceRawVcs,
|
||||
use turbo_tasks::{trace::TraceRawVcs, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::FileSystemPath,
|
||||
turbopack::core::issue::{IssueExt, IssueSeverity},
|
||||
};
|
||||
use turbopack_binding::{turbo::tasks_fs::FileSystemPathVc, turbopack::core::issue::IssueSeverity};
|
||||
|
||||
use super::options::NextFontGoogleOptionsVc;
|
||||
use super::options::NextFontGoogleOptions;
|
||||
use crate::{
|
||||
next_font::{
|
||||
font_fallback::{
|
||||
AutomaticFontFallback, FontAdjustment, FontFallback, FontFallbackVc,
|
||||
DEFAULT_SANS_SERIF_FONT, DEFAULT_SERIF_FONT,
|
||||
AutomaticFontFallback, FontAdjustment, FontFallback, DEFAULT_SANS_SERIF_FONT,
|
||||
DEFAULT_SERIF_FONT,
|
||||
},
|
||||
issue::NextFontIssue,
|
||||
util::{get_scoped_font_family, FontFamilyType},
|
||||
|
@ -46,13 +46,13 @@ struct Fallback {
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn get_font_fallback(
|
||||
context: FileSystemPathVc,
|
||||
options_vc: NextFontGoogleOptionsVc,
|
||||
request_hash: U32Vc,
|
||||
) -> Result<FontFallbackVc> {
|
||||
context: Vc<FileSystemPath>,
|
||||
options_vc: Vc<NextFontGoogleOptions>,
|
||||
request_hash: Vc<u32>,
|
||||
) -> Result<Vc<FontFallback>> {
|
||||
let options = options_vc.await?;
|
||||
Ok(match &options.fallback {
|
||||
Some(fallback) => FontFallback::Manual(StringsVc::cell(fallback.clone())).cell(),
|
||||
Some(fallback) => FontFallback::Manual(Vc::cell(fallback.clone())).cell(),
|
||||
None => {
|
||||
let metrics_json =
|
||||
load_next_json(context, "/dist/server/capsize-font-metrics.json").await?;
|
||||
|
@ -70,7 +70,7 @@ pub(super) async fn get_font_fallback(
|
|||
options_vc.font_family(),
|
||||
request_hash,
|
||||
),
|
||||
local_font_family: StringVc::cell(fallback.font_family),
|
||||
local_font_family: Vc::cell(fallback.font_family),
|
||||
adjustment: fallback.adjustment,
|
||||
}
|
||||
.cell(),
|
||||
|
@ -79,17 +79,14 @@ pub(super) async fn get_font_fallback(
|
|||
Err(_) => {
|
||||
NextFontIssue {
|
||||
path: context,
|
||||
title: StringVc::cell(format!(
|
||||
title: Vc::cell(format!(
|
||||
"Failed to find font override values for font `{}`",
|
||||
&options.font_family,
|
||||
)),
|
||||
description: StringVc::cell(
|
||||
"Skipping generating a fallback font.".to_owned(),
|
||||
),
|
||||
description: Vc::cell("Skipping generating a fallback font.".to_owned()),
|
||||
severity: IssueSeverity::Warning.cell(),
|
||||
}
|
||||
.cell()
|
||||
.as_issue()
|
||||
.emit();
|
||||
FontFallback::Error.cell()
|
||||
}
|
||||
|
|
|
@ -4,57 +4,48 @@ use anyhow::{bail, Context, Result};
|
|||
use futures::FutureExt;
|
||||
use indexmap::IndexMap;
|
||||
use indoc::formatdoc;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::{
|
||||
tasks::{
|
||||
primitives::{OptionStringVc, StringVc, U32Vc},
|
||||
CompletionVc, Value,
|
||||
},
|
||||
tasks::{Completion, Value},
|
||||
tasks_bytes::stream::SingleValue,
|
||||
tasks_env::{CommandLineProcessEnvVc, ProcessEnv},
|
||||
tasks_env::{CommandLineProcessEnv, ProcessEnv},
|
||||
tasks_fetch::fetch,
|
||||
tasks_fs::{
|
||||
json::parse_json_with_source_context, DiskFileSystemVc, File, FileContent, FileSystem,
|
||||
FileSystemPathVc,
|
||||
json::parse_json_with_source_context, DiskFileSystem, File, FileContent, FileSystem,
|
||||
FileSystemPath,
|
||||
},
|
||||
},
|
||||
turbopack::{
|
||||
core::{
|
||||
asset::AssetContent,
|
||||
context::AssetContext,
|
||||
ident::AssetIdentVc,
|
||||
issue::IssueSeverity,
|
||||
reference_type::{InnerAssetsVc, ReferenceType},
|
||||
ident::AssetIdent,
|
||||
issue::{IssueExt, IssueSeverity},
|
||||
reference_type::{InnerAssets, ReferenceType},
|
||||
resolve::{
|
||||
options::{
|
||||
ImportMapResult, ImportMapResultVc, ImportMapping, ImportMappingReplacement,
|
||||
ImportMappingReplacementVc, ImportMappingVc,
|
||||
},
|
||||
parse::{Request, RequestVc},
|
||||
pattern::QueryMapVc,
|
||||
options::{ImportMapResult, ImportMapping, ImportMappingReplacement},
|
||||
parse::Request,
|
||||
pattern::QueryMap,
|
||||
ResolveResult,
|
||||
},
|
||||
virtual_source::VirtualSourceVc,
|
||||
},
|
||||
node::{
|
||||
debug::should_debug,
|
||||
evaluate::evaluate,
|
||||
execution_context::{ExecutionContext, ExecutionContextVc},
|
||||
virtual_source::VirtualSource,
|
||||
},
|
||||
node::{debug::should_debug, evaluate::evaluate, execution_context::ExecutionContext},
|
||||
turbopack::evaluate_context::node_evaluate_asset_context,
|
||||
},
|
||||
};
|
||||
|
||||
use self::{
|
||||
font_fallback::get_font_fallback,
|
||||
options::{options_from_request, FontDataEntry, FontWeights, NextFontGoogleOptionsVc},
|
||||
options::{options_from_request, FontDataEntry, FontWeights, NextFontGoogleOptions},
|
||||
stylesheet::build_stylesheet,
|
||||
util::{get_font_axes, get_stylesheet_url},
|
||||
};
|
||||
use super::{
|
||||
font_fallback::{FontFallback, FontFallbackVc},
|
||||
font_fallback::FontFallback,
|
||||
util::{
|
||||
get_request_hash, get_request_id, get_scoped_font_family, FontCssProperties,
|
||||
FontCssPropertiesVc, FontFamilyType,
|
||||
get_request_hash, get_request_id, get_scoped_font_family, FontCssProperties, FontFamilyType,
|
||||
},
|
||||
};
|
||||
use crate::{embed_js::next_js_file_path, util::load_next_json};
|
||||
|
@ -78,13 +69,13 @@ struct FontData(IndexMap<String, FontDataEntry>);
|
|||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub(crate) struct NextFontGoogleReplacer {
|
||||
project_path: FileSystemPathVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextFontGoogleReplacerVc {
|
||||
impl NextFontGoogleReplacer {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(project_path: FileSystemPathVc) -> Self {
|
||||
pub fn new(project_path: Vc<FileSystemPath>) -> Vc<Self> {
|
||||
Self::cell(NextFontGoogleReplacer { project_path })
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +83,7 @@ impl NextFontGoogleReplacerVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ImportMappingReplacement for NextFontGoogleReplacer {
|
||||
#[turbo_tasks::function]
|
||||
fn replace(&self, _capture: &str) -> ImportMappingVc {
|
||||
fn replace(&self, _capture: String) -> Vc<ImportMapping> {
|
||||
ImportMapping::Ignore.into()
|
||||
}
|
||||
|
||||
|
@ -102,9 +93,9 @@ impl ImportMappingReplacement for NextFontGoogleReplacer {
|
|||
#[turbo_tasks::function]
|
||||
async fn result(
|
||||
&self,
|
||||
_context: FileSystemPathVc,
|
||||
request: RequestVc,
|
||||
) -> Result<ImportMapResultVc> {
|
||||
_context: Vc<FileSystemPath>,
|
||||
request: Vc<Request>,
|
||||
) -> Result<Vc<ImportMapResult>> {
|
||||
let request = &*request.await?;
|
||||
let Request::Module {
|
||||
module: _,
|
||||
|
@ -121,62 +112,65 @@ impl ImportMappingReplacement for NextFontGoogleReplacer {
|
|||
let request_hash = get_request_hash(*query_vc);
|
||||
let fallback = get_font_fallback(self.project_path, options, request_hash);
|
||||
let properties = get_font_css_properties(options, fallback, request_hash).await?;
|
||||
let js_asset = VirtualSourceVc::new(
|
||||
next_js_file_path("internal/font/google")
|
||||
.join(&format!("{}.js", get_request_id(options.font_family(), request_hash).await?)),
|
||||
FileContent::Content(
|
||||
formatdoc!(
|
||||
r#"
|
||||
import cssModule from "@vercel/turbopack-next/internal/font/google/cssmodule.module.css?{}";
|
||||
const fontData = {{
|
||||
className: cssModule.className,
|
||||
style: {{
|
||||
fontFamily: "{}",
|
||||
{}{}
|
||||
}},
|
||||
}};
|
||||
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?)),
|
||||
AssetContent::file(FileContent::Content(
|
||||
formatdoc!(
|
||||
r#"
|
||||
import cssModule from "@vercel/turbopack-next/internal/font/google/cssmodule.module.css?{}";
|
||||
const fontData = {{
|
||||
className: cssModule.className,
|
||||
style: {{
|
||||
fontFamily: "{}",
|
||||
{}{}
|
||||
}},
|
||||
}};
|
||||
|
||||
if (cssModule.variable != null) {{
|
||||
fontData.variable = cssModule.variable;
|
||||
}}
|
||||
if (cssModule.variable != null) {{
|
||||
fontData.variable = cssModule.variable;
|
||||
}}
|
||||
|
||||
export default fontData;
|
||||
"#,
|
||||
// Pass along whichever options we received to the css handler
|
||||
qstring::QString::new(query.as_ref().unwrap().iter().collect()),
|
||||
properties.font_family.await?,
|
||||
properties
|
||||
.weight
|
||||
.await?
|
||||
.as_ref()
|
||||
.map(|w| format!("fontWeight: {},\n", w))
|
||||
.unwrap_or_else(|| "".to_owned()),
|
||||
properties
|
||||
.style
|
||||
.await?
|
||||
.as_ref()
|
||||
.map(|s| format!("fontStyle: \"{}\",\n", s))
|
||||
.unwrap_or_else(|| "".to_owned()),
|
||||
)
|
||||
.into(),
|
||||
export default fontData;
|
||||
"#,
|
||||
// Pass along whichever options we received to the css handler
|
||||
qstring::QString::new(query.as_ref().unwrap().iter().collect()),
|
||||
properties.font_family.await?,
|
||||
properties
|
||||
.weight
|
||||
.await?
|
||||
.as_ref()
|
||||
.map(|w| format!("fontWeight: {},\n", w))
|
||||
.unwrap_or_else(|| "".to_owned()),
|
||||
properties
|
||||
.style
|
||||
.await?
|
||||
.as_ref()
|
||||
.map(|s| format!("fontStyle: \"{}\",\n", s))
|
||||
.unwrap_or_else(|| "".to_owned()),
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
)
|
||||
.into()),
|
||||
);
|
||||
|
||||
Ok(ImportMapResult::Result(ResolveResult::asset(js_asset.into()).into()).into())
|
||||
Ok(ImportMapResult::Result(ResolveResult::asset(Vc::upcast(js_asset)).into()).into())
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextFontGoogleCssModuleReplacer {
|
||||
project_path: FileSystemPathVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextFontGoogleCssModuleReplacerVc {
|
||||
impl NextFontGoogleCssModuleReplacer {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(project_path: FileSystemPathVc, execution_context: ExecutionContextVc) -> Self {
|
||||
pub fn new(
|
||||
project_path: Vc<FileSystemPath>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
) -> Vc<Self> {
|
||||
Self::cell(NextFontGoogleCssModuleReplacer {
|
||||
project_path,
|
||||
execution_context,
|
||||
|
@ -187,7 +181,7 @@ impl NextFontGoogleCssModuleReplacerVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
|
||||
#[turbo_tasks::function]
|
||||
fn replace(&self, _capture: &str) -> ImportMappingVc {
|
||||
fn replace(&self, _capture: String) -> Vc<ImportMapping> {
|
||||
ImportMapping::Ignore.into()
|
||||
}
|
||||
|
||||
|
@ -198,9 +192,9 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
|
|||
#[turbo_tasks::function]
|
||||
async fn result(
|
||||
&self,
|
||||
_context: FileSystemPathVc,
|
||||
request: RequestVc,
|
||||
) -> Result<ImportMapResultVc> {
|
||||
_context: Vc<FileSystemPath>,
|
||||
request: Vc<Request>,
|
||||
) -> Result<Vc<ImportMapResult>> {
|
||||
let request = &*request.await?;
|
||||
let Request::Module {
|
||||
module: _,
|
||||
|
@ -220,7 +214,7 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
|
|||
options.font_family(),
|
||||
request_hash,
|
||||
);
|
||||
let css_virtual_path = next_js_file_path("internal/font/google").join(&format!(
|
||||
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?
|
||||
));
|
||||
|
@ -228,8 +222,10 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
|
|||
// 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 = CommandLineProcessEnvVc::new().as_process_env();
|
||||
let mocked_responses_path = &*env.read("NEXT_FONT_GOOGLE_MOCKED_RESPONSES").await?;
|
||||
let env = Vc::upcast::<Box<dyn ProcessEnv>>(CommandLineProcessEnv::new());
|
||||
let mocked_responses_path = &*env
|
||||
.read("NEXT_FONT_GOOGLE_MOCKED_RESPONSES".to_string())
|
||||
.await?;
|
||||
let stylesheet_str = mocked_responses_path
|
||||
.as_ref()
|
||||
.map_or_else(
|
||||
|
@ -248,26 +244,28 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
|
|||
};
|
||||
|
||||
let font_fallback = get_font_fallback(self.project_path, options, request_hash);
|
||||
let css_asset = VirtualSourceVc::new(
|
||||
let css_asset = VirtualSource::new(
|
||||
css_virtual_path,
|
||||
FileContent::Content(
|
||||
build_stylesheet(
|
||||
OptionStringVc::cell(stylesheet),
|
||||
get_font_css_properties(options, font_fallback, request_hash),
|
||||
font_fallback,
|
||||
AssetContent::file(
|
||||
FileContent::Content(
|
||||
build_stylesheet(
|
||||
Vc::cell(stylesheet),
|
||||
get_font_css_properties(options, font_fallback, request_hash),
|
||||
font_fallback,
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
);
|
||||
|
||||
Ok(ImportMapResult::Result(ResolveResult::asset(css_asset.into()).into()).into())
|
||||
Ok(ImportMapResult::Result(ResolveResult::asset(Vc::upcast(css_asset)).into()).into())
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn load_font_data(project_root: FileSystemPathVc) -> Result<FontDataVc> {
|
||||
async fn load_font_data(project_root: Vc<FileSystemPath>) -> Result<Vc<FontData>> {
|
||||
let data: FontData = load_next_json(
|
||||
project_root,
|
||||
"/dist/compiled/@next/font/dist/google/font-data.json",
|
||||
|
@ -281,13 +279,13 @@ async fn load_font_data(project_root: FileSystemPathVc) -> Result<FontDataVc> {
|
|||
/// font family names.
|
||||
#[turbo_tasks::function]
|
||||
async fn update_google_stylesheet(
|
||||
stylesheet: StringVc,
|
||||
options: NextFontGoogleOptionsVc,
|
||||
scoped_font_family: StringVc,
|
||||
) -> Result<StringVc> {
|
||||
stylesheet: Vc<String>,
|
||||
options: Vc<NextFontGoogleOptions>,
|
||||
scoped_font_family: Vc<String>,
|
||||
) -> Result<Vc<String>> {
|
||||
// Update font-family definitions to the scoped name
|
||||
// TODO: Do this more resiliently, e.g. transforming an swc ast
|
||||
Ok(StringVc::cell(stylesheet.await?.replace(
|
||||
Ok(Vc::cell(stylesheet.await?.replace(
|
||||
&format!("font-family: '{}';", &*options.await?.font_family),
|
||||
&format!("font-family: '{}';", &*scoped_font_family.await?),
|
||||
)))
|
||||
|
@ -295,23 +293,26 @@ async fn update_google_stylesheet(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
async fn get_stylesheet_url_from_options(
|
||||
options: NextFontGoogleOptionsVc,
|
||||
font_data: FontDataVc,
|
||||
) -> Result<StringVc> {
|
||||
options: Vc<NextFontGoogleOptions>,
|
||||
font_data: Vc<FontData>,
|
||||
) -> Result<Vc<String>> {
|
||||
#[allow(unused_mut, unused_assignments)] // This is used in test environments
|
||||
let mut css_url: Option<String> = None;
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
use turbopack_binding::turbo::tasks_env::{CommandLineProcessEnvVc, ProcessEnv};
|
||||
use turbopack_binding::turbo::tasks_env::{CommandLineProcessEnv, ProcessEnv};
|
||||
|
||||
let env = CommandLineProcessEnvVc::new();
|
||||
if let Some(url) = &*env.read("TURBOPACK_TEST_ONLY_MOCK_SERVER").await? {
|
||||
let env = CommandLineProcessEnv::new();
|
||||
if let Some(url) = &*env
|
||||
.read("TURBOPACK_TEST_ONLY_MOCK_SERVER".to_string())
|
||||
.await?
|
||||
{
|
||||
css_url = Some(format!("{}/css2", url));
|
||||
}
|
||||
}
|
||||
|
||||
let options = options.await?;
|
||||
Ok(StringVc::cell(get_stylesheet_url(
|
||||
Ok(Vc::cell(get_stylesheet_url(
|
||||
css_url.as_deref().unwrap_or(GOOGLE_FONTS_STYLESHEET_URL),
|
||||
&options.font_family,
|
||||
&get_font_axes(
|
||||
|
@ -327,10 +328,10 @@ async fn get_stylesheet_url_from_options(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
async fn get_font_css_properties(
|
||||
options_vc: NextFontGoogleOptionsVc,
|
||||
font_fallback: FontFallbackVc,
|
||||
request_hash: U32Vc,
|
||||
) -> Result<FontCssPropertiesVc> {
|
||||
options_vc: Vc<NextFontGoogleOptions>,
|
||||
font_fallback: Vc<FontFallback>,
|
||||
request_hash: Vc<u32>,
|
||||
) -> Result<Vc<FontCssProperties>> {
|
||||
let options = &*options_vc.await?;
|
||||
let scoped_font_family = &*get_scoped_font_family(
|
||||
FontFamilyType::WebFont.cell(),
|
||||
|
@ -352,22 +353,22 @@ async fn get_font_css_properties(
|
|||
FontFallback::Error => {}
|
||||
}
|
||||
|
||||
Ok(FontCssPropertiesVc::cell(FontCssProperties {
|
||||
font_family: StringVc::cell(font_families.join(", ")),
|
||||
weight: OptionStringVc::cell(match &options.weights {
|
||||
Ok(FontCssProperties::cell(FontCssProperties {
|
||||
font_family: Vc::cell(font_families.join(", ")),
|
||||
weight: Vc::cell(match &options.weights {
|
||||
FontWeights::Variable => None,
|
||||
FontWeights::Fixed(weights) => weights.first().map(|w| w.to_string()),
|
||||
}),
|
||||
style: OptionStringVc::cell(options.styles.first().cloned()),
|
||||
variable: OptionStringVc::cell(options.variable.clone()),
|
||||
style: Vc::cell(options.styles.first().cloned()),
|
||||
variable: Vc::cell(options.variable.clone()),
|
||||
}))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn font_options_from_query_map(
|
||||
query: QueryMapVc,
|
||||
font_data: FontDataVc,
|
||||
) -> Result<NextFontGoogleOptionsVc> {
|
||||
query: Vc<QueryMap>,
|
||||
font_data: Vc<FontData>,
|
||||
) -> Result<Vc<NextFontGoogleOptions>> {
|
||||
let query_map = &*query.await?;
|
||||
// These are invariants from the next/font swc transform. Regular errors instead
|
||||
// of Issues should be okay.
|
||||
|
@ -384,16 +385,16 @@ async fn font_options_from_query_map(
|
|||
};
|
||||
|
||||
options_from_request(&parse_json_with_source_context(json)?, &*font_data.await?)
|
||||
.map(|o| NextFontGoogleOptionsVc::new(Value::new(o)))
|
||||
.map(|o| NextFontGoogleOptions::new(Value::new(o)))
|
||||
}
|
||||
|
||||
async fn fetch_real_stylesheet(
|
||||
stylesheet_url: StringVc,
|
||||
css_virtual_path: FileSystemPathVc,
|
||||
) -> Result<Option<StringVc>> {
|
||||
stylesheet_url: Vc<String>,
|
||||
css_virtual_path: Vc<FileSystemPath>,
|
||||
) -> Result<Option<Vc<String>>> {
|
||||
let stylesheet = fetch(
|
||||
stylesheet_url,
|
||||
OptionStringVc::cell(Some(USER_AGENT_FOR_GOOGLE_FONTS.to_owned())),
|
||||
Vc::cell(Some(USER_AGENT_FOR_GOOGLE_FONTS.to_owned())),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
@ -408,7 +409,6 @@ async fn fetch_real_stylesheet(
|
|||
// TODO(WEB-283): Use fallback in dev in this case
|
||||
// TODO(WEB-293): Fail production builds (not dev) in this case
|
||||
err.to_issue(IssueSeverity::Warning.into(), css_virtual_path)
|
||||
.as_issue()
|
||||
.emit();
|
||||
|
||||
None
|
||||
|
@ -417,12 +417,12 @@ async fn fetch_real_stylesheet(
|
|||
}
|
||||
|
||||
async fn get_mock_stylesheet(
|
||||
stylesheet_url: StringVc,
|
||||
stylesheet_url: Vc<String>,
|
||||
mocked_responses_path: &str,
|
||||
execution_context: ExecutionContextVc,
|
||||
) -> Result<Option<StringVc>> {
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
) -> Result<Option<Vc<String>>> {
|
||||
let response_path = Path::new(&mocked_responses_path);
|
||||
let mock_fs = DiskFileSystemVc::new(
|
||||
let mock_fs = Vc::upcast::<Box<dyn FileSystem>>(DiskFileSystem::new(
|
||||
"mock".to_string(),
|
||||
response_path
|
||||
.parent()
|
||||
|
@ -430,8 +430,7 @@ async fn get_mock_stylesheet(
|
|||
.to_str()
|
||||
.context("Must exist")?
|
||||
.to_string(),
|
||||
)
|
||||
.as_file_system();
|
||||
));
|
||||
|
||||
let ExecutionContext {
|
||||
env,
|
||||
|
@ -439,34 +438,35 @@ async fn get_mock_stylesheet(
|
|||
chunking_context,
|
||||
} = *execution_context.await?;
|
||||
let context = node_evaluate_asset_context(execution_context, None, None);
|
||||
let loader_path = mock_fs.root().join("loader.js");
|
||||
let loader_path = mock_fs.root().join("loader.js".to_string());
|
||||
let mocked_response_asset = context.process(
|
||||
VirtualSourceVc::new(
|
||||
Vc::upcast(VirtualSource::new(
|
||||
loader_path,
|
||||
File::from(format!(
|
||||
"import data from './{}'; export default function load() {{ return data; }};",
|
||||
response_path
|
||||
.file_name()
|
||||
.context("Must exist")?
|
||||
.to_string_lossy(),
|
||||
))
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::empty())),
|
||||
AssetContent::file(
|
||||
File::from(format!(
|
||||
"import data from './{}'; export default function load() {{ return data; }};",
|
||||
response_path
|
||||
.file_name()
|
||||
.context("Must exist")?
|
||||
.to_string_lossy(),
|
||||
))
|
||||
.into(),
|
||||
),
|
||||
)),
|
||||
Value::new(ReferenceType::Internal(InnerAssets::empty())),
|
||||
);
|
||||
|
||||
let root = mock_fs.root();
|
||||
let val = evaluate(
|
||||
mocked_response_asset.into(),
|
||||
Vc::upcast(mocked_response_asset),
|
||||
root,
|
||||
env,
|
||||
AssetIdentVc::from_path(loader_path),
|
||||
AssetIdent::from_path(loader_path),
|
||||
context,
|
||||
chunking_context,
|
||||
None,
|
||||
vec![],
|
||||
CompletionVc::immutable(),
|
||||
Completion::immutable(),
|
||||
should_debug("next_font::google"),
|
||||
)
|
||||
.await?;
|
||||
|
@ -479,7 +479,7 @@ async fn get_mock_stylesheet(
|
|||
.get(&*stylesheet_url.await?)
|
||||
.context("url not found")?
|
||||
.clone()
|
||||
.map(StringVc::cell))
|
||||
.map(Vc::cell))
|
||||
}
|
||||
_ => {
|
||||
panic!("Unexpected error evaluating JS")
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use anyhow::{anyhow, Context, Result};
|
||||
use indexmap::{indexset, IndexMap, IndexSet};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turbopack_binding::turbo::tasks::{primitives::StringVc, trace::TraceRawVcs, Value};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbo::tasks::{trace::TraceRawVcs, Value};
|
||||
|
||||
use super::request::{NextFontRequest, OneOrManyStrings};
|
||||
|
||||
|
@ -28,15 +29,15 @@ pub(super) struct NextFontGoogleOptions {
|
|||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextFontGoogleOptionsVc {
|
||||
impl NextFontGoogleOptions {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(options: Value<NextFontGoogleOptions>) -> NextFontGoogleOptionsVc {
|
||||
pub fn new(options: Value<NextFontGoogleOptions>) -> Vc<NextFontGoogleOptions> {
|
||||
Self::cell(options.into_value())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn font_family(self) -> Result<StringVc> {
|
||||
Ok(StringVc::cell((*self.await?.font_family).to_owned()))
|
||||
pub async fn font_family(self: Vc<Self>) -> Result<Vc<String>> {
|
||||
Ok(Vc::cell((*self.await?.font_family).to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
use anyhow::Result;
|
||||
use turbopack_binding::turbo::tasks::primitives::{OptionStringVc, StringVc};
|
||||
use turbo_tasks::Vc;
|
||||
|
||||
use super::FontCssPropertiesVc;
|
||||
use super::FontCssProperties;
|
||||
use crate::next_font::{
|
||||
font_fallback::{FontFallbackVc, FontFallbacksVc},
|
||||
font_fallback::FontFallback,
|
||||
stylesheet::{build_fallback_definition, build_font_class_rules},
|
||||
};
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn build_stylesheet(
|
||||
base_stylesheet: OptionStringVc,
|
||||
font_css_properties: FontCssPropertiesVc,
|
||||
font_fallback: FontFallbackVc,
|
||||
) -> Result<StringVc> {
|
||||
base_stylesheet: Vc<Option<String>>,
|
||||
font_css_properties: Vc<FontCssProperties>,
|
||||
font_fallback: Vc<FontFallback>,
|
||||
) -> Result<Vc<String>> {
|
||||
let base_stylesheet = &*base_stylesheet.await?;
|
||||
let mut stylesheet = base_stylesheet
|
||||
.as_ref()
|
||||
.map_or_else(|| "".to_owned(), |s| s.to_owned());
|
||||
|
||||
stylesheet
|
||||
.push_str(&build_fallback_definition(FontFallbacksVc::cell(vec![font_fallback])).await?);
|
||||
stylesheet.push_str(&build_fallback_definition(Vc::cell(vec![font_fallback])).await?);
|
||||
stylesheet.push_str(&build_font_class_rules(font_css_properties).await?);
|
||||
Ok(StringVc::cell(stylesheet))
|
||||
Ok(Vc::cell(stylesheet))
|
||||
}
|
||||
|
|
|
@ -1,41 +1,41 @@
|
|||
use turbo_tasks::primitives::StringVc;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::FileSystemPathVc,
|
||||
turbopack::core::issue::{Issue, IssueSeverityVc, IssueVc},
|
||||
turbo::tasks_fs::FileSystemPath,
|
||||
turbopack::core::issue::{Issue, IssueSeverity},
|
||||
};
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub(crate) struct NextFontIssue {
|
||||
pub(crate) path: FileSystemPathVc,
|
||||
pub(crate) title: StringVc,
|
||||
pub(crate) description: StringVc,
|
||||
pub(crate) severity: IssueSeverityVc,
|
||||
pub(crate) path: Vc<FileSystemPath>,
|
||||
pub(crate) title: Vc<String>,
|
||||
pub(crate) description: Vc<String>,
|
||||
pub(crate) severity: Vc<IssueSeverity>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Issue for NextFontIssue {
|
||||
#[turbo_tasks::function]
|
||||
fn category(&self) -> StringVc {
|
||||
StringVc::cell("other".to_string())
|
||||
fn category(&self) -> Vc<String> {
|
||||
Vc::cell("other".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn severity(&self) -> IssueSeverityVc {
|
||||
fn severity(&self) -> Vc<IssueSeverity> {
|
||||
self.severity
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn context(&self) -> FileSystemPathVc {
|
||||
fn context(&self) -> Vc<FileSystemPath> {
|
||||
self.path
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn title(&self) -> StringVc {
|
||||
fn title(&self) -> Vc<String> {
|
||||
self.title
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn description(&self) -> StringVc {
|
||||
fn description(&self) -> Vc<String> {
|
||||
self.description
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,18 +3,16 @@ use allsorts::{
|
|||
Font,
|
||||
};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use turbopack_binding::turbo::{
|
||||
tasks::primitives::{StringVc, StringsVc, U32Vc},
|
||||
tasks_fs::{FileContent, FileSystemPathVc},
|
||||
};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbo::tasks_fs::{FileContent, FileSystemPath};
|
||||
|
||||
use super::{
|
||||
options::{FontDescriptor, FontDescriptors, FontWeight, NextFontLocalOptionsVc},
|
||||
options::{FontDescriptor, FontDescriptors, FontWeight, NextFontLocalOptions},
|
||||
request::AdjustFontFallback,
|
||||
};
|
||||
use crate::next_font::{
|
||||
font_fallback::{
|
||||
AutomaticFontFallback, DefaultFallbackFont, FontAdjustment, FontFallback, FontFallbacksVc,
|
||||
AutomaticFontFallback, DefaultFallbackFont, FontAdjustment, FontFallback, FontFallbacks,
|
||||
DEFAULT_SANS_SERIF_FONT, DEFAULT_SERIF_FONT,
|
||||
},
|
||||
util::{get_scoped_font_family, FontFamilyType},
|
||||
|
@ -28,10 +26,10 @@ static BOLD_WEIGHT: f64 = 700.0;
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn get_font_fallbacks(
|
||||
context: FileSystemPathVc,
|
||||
options_vc: NextFontLocalOptionsVc,
|
||||
request_hash: U32Vc,
|
||||
) -> Result<FontFallbacksVc> {
|
||||
context: Vc<FileSystemPath>,
|
||||
options_vc: Vc<NextFontLocalOptions>,
|
||||
request_hash: Vc<u32>,
|
||||
) -> Result<Vc<FontFallbacks>> {
|
||||
let options = &*options_vc.await?;
|
||||
let mut font_fallbacks = vec![];
|
||||
let scoped_font_family = get_scoped_font_family(
|
||||
|
@ -45,7 +43,7 @@ pub(super) async fn get_font_fallbacks(
|
|||
FontFallback::Automatic(
|
||||
AutomaticFontFallback {
|
||||
scoped_font_family,
|
||||
local_font_family: StringVc::cell("Arial".to_owned()),
|
||||
local_font_family: Vc::cell("Arial".to_owned()),
|
||||
adjustment: Some(
|
||||
get_font_adjustment(context, options_vc, &DEFAULT_SANS_SERIF_FONT).await?,
|
||||
),
|
||||
|
@ -58,7 +56,7 @@ pub(super) async fn get_font_fallbacks(
|
|||
FontFallback::Automatic(
|
||||
AutomaticFontFallback {
|
||||
scoped_font_family,
|
||||
local_font_family: StringVc::cell("Times New Roman".to_owned()),
|
||||
local_font_family: Vc::cell("Times New Roman".to_owned()),
|
||||
adjustment: Some(
|
||||
get_font_adjustment(context, options_vc, &DEFAULT_SERIF_FONT).await?,
|
||||
),
|
||||
|
@ -71,20 +69,20 @@ pub(super) async fn get_font_fallbacks(
|
|||
};
|
||||
|
||||
if let Some(fallback) = &options.fallback {
|
||||
font_fallbacks.push(FontFallback::Manual(StringsVc::cell(fallback.clone())).into());
|
||||
font_fallbacks.push(FontFallback::Manual(Vc::cell(fallback.clone())).into());
|
||||
}
|
||||
|
||||
Ok(FontFallbacksVc::cell(font_fallbacks))
|
||||
Ok(Vc::cell(font_fallbacks))
|
||||
}
|
||||
|
||||
async fn get_font_adjustment(
|
||||
context: FileSystemPathVc,
|
||||
options: NextFontLocalOptionsVc,
|
||||
context: Vc<FileSystemPath>,
|
||||
options: Vc<NextFontLocalOptions>,
|
||||
fallback_font: &DefaultFallbackFont,
|
||||
) -> Result<FontAdjustment> {
|
||||
let options = &*options.await?;
|
||||
let main_descriptor = pick_font_for_fallback_generation(&options.fonts)?;
|
||||
let font_file = &*context.join(&main_descriptor.path).read().await?;
|
||||
let font_file = &*context.join(main_descriptor.path.clone()).read().await?;
|
||||
let font_file_rope = match font_file {
|
||||
FileContent::NotFound => bail!("Expected font file content"),
|
||||
FileContent::Content(file) => file.content(),
|
||||
|
|
|
@ -1,37 +1,30 @@
|
|||
use anyhow::{bail, Context, Result};
|
||||
use indoc::formatdoc;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::{
|
||||
tasks::{
|
||||
primitives::{OptionStringVc, U32Vc},
|
||||
Value,
|
||||
},
|
||||
tasks_fs::{json::parse_json_with_source_context, FileContent, FileSystemPathVc},
|
||||
tasks::Value,
|
||||
tasks_fs::{json::parse_json_with_source_context, FileContent, FileSystemPath},
|
||||
},
|
||||
turbopack::core::{
|
||||
asset::AssetContent,
|
||||
resolve::{
|
||||
options::{
|
||||
ImportMapResult, ImportMapResultVc, ImportMapping, ImportMappingReplacement,
|
||||
ImportMappingReplacementVc, ImportMappingVc,
|
||||
},
|
||||
parse::{Request, RequestVc},
|
||||
pattern::QueryMapVc,
|
||||
options::{ImportMapResult, ImportMapping, ImportMappingReplacement},
|
||||
parse::Request,
|
||||
pattern::QueryMap,
|
||||
ResolveResult,
|
||||
},
|
||||
virtual_source::VirtualSourceVc,
|
||||
virtual_source::VirtualSource,
|
||||
},
|
||||
};
|
||||
|
||||
use self::{
|
||||
font_fallback::get_font_fallbacks,
|
||||
options::{options_from_request, FontDescriptors, NextFontLocalOptionsVc},
|
||||
options::{options_from_request, FontDescriptors, NextFontLocalOptions},
|
||||
stylesheet::build_stylesheet,
|
||||
util::build_font_family_string,
|
||||
};
|
||||
use super::{
|
||||
font_fallback::FontFallbacksVc,
|
||||
util::{FontCssProperties, FontCssPropertiesVc},
|
||||
};
|
||||
use super::{font_fallback::FontFallbacks, util::FontCssProperties};
|
||||
use crate::next_font::{
|
||||
local::options::FontWeight,
|
||||
util::{get_request_hash, get_request_id},
|
||||
|
@ -45,13 +38,13 @@ pub mod util;
|
|||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub(crate) struct NextFontLocalReplacer {
|
||||
project_path: FileSystemPathVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextFontLocalReplacerVc {
|
||||
impl NextFontLocalReplacer {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(project_path: FileSystemPathVc) -> Self {
|
||||
pub fn new(project_path: Vc<FileSystemPath>) -> Vc<Self> {
|
||||
Self::cell(NextFontLocalReplacer { project_path })
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +52,7 @@ impl NextFontLocalReplacerVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ImportMappingReplacement for NextFontLocalReplacer {
|
||||
#[turbo_tasks::function]
|
||||
fn replace(&self, _capture: &str) -> ImportMappingVc {
|
||||
fn replace(&self, _capture: String) -> Vc<ImportMapping> {
|
||||
ImportMapping::Ignore.into()
|
||||
}
|
||||
|
||||
|
@ -69,9 +62,9 @@ impl ImportMappingReplacement for NextFontLocalReplacer {
|
|||
#[turbo_tasks::function]
|
||||
async fn result(
|
||||
&self,
|
||||
context: FileSystemPathVc,
|
||||
request: RequestVc,
|
||||
) -> Result<ImportMapResultVc> {
|
||||
context: Vc<FileSystemPath>,
|
||||
request: Vc<Request>,
|
||||
) -> Result<Vc<ImportMapResult>> {
|
||||
let Request::Module {
|
||||
module: _,
|
||||
path: _,
|
||||
|
@ -119,27 +112,27 @@ impl ImportMappingReplacement for NextFontLocalReplacer {
|
|||
.map(|s| format!("fontStyle: \"{}\",\n", s))
|
||||
.unwrap_or_else(|| "".to_owned()),
|
||||
);
|
||||
let js_asset = VirtualSourceVc::new(
|
||||
context.join(&format!(
|
||||
let js_asset = VirtualSource::new(
|
||||
context.join(format!(
|
||||
"{}.js",
|
||||
get_request_id(options_vc.font_family(), request_hash).await?
|
||||
)),
|
||||
FileContent::Content(file_content.into()).into(),
|
||||
AssetContent::file(FileContent::Content(file_content.into()).into()),
|
||||
);
|
||||
|
||||
Ok(ImportMapResult::Result(ResolveResult::asset(js_asset.into()).into()).into())
|
||||
Ok(ImportMapResult::Result(ResolveResult::asset(Vc::upcast(js_asset)).into()).into())
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextFontLocalCssModuleReplacer {
|
||||
project_path: FileSystemPathVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextFontLocalCssModuleReplacerVc {
|
||||
impl NextFontLocalCssModuleReplacer {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(project_path: FileSystemPathVc) -> Self {
|
||||
pub fn new(project_path: Vc<FileSystemPath>) -> Vc<Self> {
|
||||
Self::cell(NextFontLocalCssModuleReplacer { project_path })
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +140,7 @@ impl NextFontLocalCssModuleReplacerVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ImportMappingReplacement for NextFontLocalCssModuleReplacer {
|
||||
#[turbo_tasks::function]
|
||||
fn replace(&self, _capture: &str) -> ImportMappingVc {
|
||||
fn replace(&self, _capture: String) -> Vc<ImportMapping> {
|
||||
ImportMapping::Ignore.into()
|
||||
}
|
||||
|
||||
|
@ -158,9 +151,9 @@ impl ImportMappingReplacement for NextFontLocalCssModuleReplacer {
|
|||
#[turbo_tasks::function]
|
||||
async fn result(
|
||||
&self,
|
||||
context: FileSystemPathVc,
|
||||
request: RequestVc,
|
||||
) -> Result<ImportMapResultVc> {
|
||||
context: Vc<FileSystemPath>,
|
||||
request: Vc<Request>,
|
||||
) -> Result<Vc<ImportMapResult>> {
|
||||
let request = &*request.await?;
|
||||
let Request::Module {
|
||||
module: _,
|
||||
|
@ -173,7 +166,7 @@ impl ImportMappingReplacement for NextFontLocalCssModuleReplacer {
|
|||
|
||||
let options = font_options_from_query_map(*query_vc);
|
||||
let request_hash = get_request_hash(*query_vc);
|
||||
let css_virtual_path = context.join(&format!(
|
||||
let css_virtual_path = context.join(format!(
|
||||
"/{}.module.css",
|
||||
get_request_id(options.font_family(), request_hash).await?
|
||||
));
|
||||
|
@ -187,26 +180,26 @@ impl ImportMappingReplacement for NextFontLocalCssModuleReplacer {
|
|||
)
|
||||
.await?;
|
||||
|
||||
let css_asset = VirtualSourceVc::new(
|
||||
let css_asset = VirtualSource::new(
|
||||
css_virtual_path,
|
||||
FileContent::Content(stylesheet.into()).into(),
|
||||
AssetContent::file(FileContent::Content(stylesheet.into()).into()),
|
||||
);
|
||||
|
||||
Ok(ImportMapResult::Result(ResolveResult::asset(css_asset.into()).into()).into())
|
||||
Ok(ImportMapResult::Result(ResolveResult::asset(Vc::upcast(css_asset)).into()).into())
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn get_font_css_properties(
|
||||
options_vc: NextFontLocalOptionsVc,
|
||||
font_fallbacks: FontFallbacksVc,
|
||||
request_hash: U32Vc,
|
||||
) -> Result<FontCssPropertiesVc> {
|
||||
options_vc: Vc<NextFontLocalOptions>,
|
||||
font_fallbacks: Vc<FontFallbacks>,
|
||||
request_hash: Vc<u32>,
|
||||
) -> Result<Vc<FontCssProperties>> {
|
||||
let options = &*options_vc.await?;
|
||||
|
||||
Ok(FontCssPropertiesVc::cell(FontCssProperties {
|
||||
Ok(FontCssProperties::cell(FontCssProperties {
|
||||
font_family: build_font_family_string(options_vc, font_fallbacks, request_hash),
|
||||
weight: OptionStringVc::cell(match &options.fonts {
|
||||
weight: Vc::cell(match &options.fonts {
|
||||
FontDescriptors::Many(_) => None,
|
||||
// When the user only provided a top-level font file, include the font weight in the
|
||||
// className selector rules
|
||||
|
@ -218,18 +211,18 @@ async fn get_font_css_properties(
|
|||
.filter(|w| !matches!(w, FontWeight::Variable(_, _)))
|
||||
.map(|w| w.to_string()),
|
||||
}),
|
||||
style: OptionStringVc::cell(match &options.fonts {
|
||||
style: Vc::cell(match &options.fonts {
|
||||
FontDescriptors::Many(_) => None,
|
||||
// When the user only provided a top-level font file, include the font style in the
|
||||
// className selector rules
|
||||
FontDescriptors::One(descriptor) => descriptor.style.clone(),
|
||||
}),
|
||||
variable: OptionStringVc::cell(options.variable.clone()),
|
||||
variable: Vc::cell(options.variable.clone()),
|
||||
}))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn font_options_from_query_map(query: QueryMapVc) -> Result<NextFontLocalOptionsVc> {
|
||||
async fn font_options_from_query_map(query: Vc<QueryMap>) -> Result<Vc<NextFontLocalOptions>> {
|
||||
let query_map = &*query.await?;
|
||||
// These are invariants from the next/font swc transform. Regular errors instead
|
||||
// of Issues should be okay.
|
||||
|
@ -246,5 +239,5 @@ async fn font_options_from_query_map(query: QueryMapVc) -> Result<NextFontLocalO
|
|||
};
|
||||
|
||||
options_from_request(&parse_json_with_source_context(json)?)
|
||||
.map(|o| NextFontLocalOptionsVc::new(Value::new(o)))
|
||||
.map(|o| NextFontLocalOptions::new(Value::new(o)))
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@ use std::{fmt::Display, str::FromStr};
|
|||
|
||||
use anyhow::{Context, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turbopack_binding::turbo::tasks::{primitives::StringVc, trace::TraceRawVcs, Value};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbo::tasks::{trace::TraceRawVcs, Value};
|
||||
|
||||
use super::request::{
|
||||
AdjustFontFallback, NextFontLocalRequest, NextFontLocalRequestArguments, SrcDescriptor,
|
||||
|
@ -34,15 +35,15 @@ pub(super) struct NextFontLocalOptions {
|
|||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextFontLocalOptionsVc {
|
||||
impl NextFontLocalOptions {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(options: Value<NextFontLocalOptions>) -> NextFontLocalOptionsVc {
|
||||
pub fn new(options: Value<NextFontLocalOptions>) -> Vc<NextFontLocalOptions> {
|
||||
Self::cell(options.into_value())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn font_family(self) -> Result<StringVc> {
|
||||
Ok(StringVc::cell((*self.await?.variable_name).to_owned()))
|
||||
pub async fn font_family(self: Vc<Self>) -> Result<Vc<String>> {
|
||||
Ok(Vc::cell((*self.await?.variable_name).to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
use anyhow::{bail, Result};
|
||||
use indoc::formatdoc;
|
||||
use turbopack_binding::turbo::tasks::primitives::{StringVc, U32Vc};
|
||||
use turbo_tasks::Vc;
|
||||
|
||||
use super::options::{FontDescriptors, NextFontLocalOptionsVc};
|
||||
use super::options::{FontDescriptors, NextFontLocalOptions};
|
||||
use crate::next_font::{
|
||||
font_fallback::FontFallbacksVc,
|
||||
font_fallback::FontFallbacks,
|
||||
stylesheet::{build_fallback_definition, build_font_class_rules},
|
||||
util::{get_scoped_font_family, FontCssPropertiesVc, FontFamilyType},
|
||||
util::{get_scoped_font_family, FontCssProperties, FontFamilyType},
|
||||
};
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn build_stylesheet(
|
||||
options: NextFontLocalOptionsVc,
|
||||
fallbacks: FontFallbacksVc,
|
||||
css_properties: FontCssPropertiesVc,
|
||||
request_hash: U32Vc,
|
||||
) -> Result<StringVc> {
|
||||
options: Vc<NextFontLocalOptions>,
|
||||
fallbacks: Vc<FontFallbacks>,
|
||||
css_properties: Vc<FontCssProperties>,
|
||||
request_hash: Vc<u32>,
|
||||
) -> Result<Vc<String>> {
|
||||
let scoped_font_family = get_scoped_font_family(
|
||||
FontFamilyType::WebFont.cell(),
|
||||
options.font_family(),
|
||||
request_hash,
|
||||
);
|
||||
|
||||
Ok(StringVc::cell(formatdoc!(
|
||||
Ok(Vc::cell(formatdoc!(
|
||||
r#"
|
||||
{}
|
||||
{}
|
||||
|
@ -37,9 +37,9 @@ pub(super) async fn build_stylesheet(
|
|||
/// 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: StringVc,
|
||||
options: NextFontLocalOptionsVc,
|
||||
) -> Result<StringVc> {
|
||||
scoped_font_family: Vc<String>,
|
||||
options: Vc<NextFontLocalOptions>,
|
||||
) -> Result<Vc<String>> {
|
||||
let options = &*options.await?;
|
||||
|
||||
let mut definitions = String::new();
|
||||
|
@ -75,7 +75,7 @@ pub(super) async fn build_font_face_definitions(
|
|||
));
|
||||
}
|
||||
|
||||
Ok(StringVc::cell(definitions))
|
||||
Ok(Vc::cell(definitions))
|
||||
}
|
||||
|
||||
/// Used as e.g. `format('woff')` in `src` properties in `@font-face`
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
use anyhow::Result;
|
||||
use turbopack_binding::turbo::tasks::primitives::{StringVc, U32Vc};
|
||||
use turbo_tasks::Vc;
|
||||
|
||||
use super::options::NextFontLocalOptionsVc;
|
||||
use super::options::NextFontLocalOptions;
|
||||
use crate::next_font::{
|
||||
font_fallback::{FontFallback, FontFallbacksVc},
|
||||
font_fallback::{FontFallback, FontFallbacks},
|
||||
util::{get_scoped_font_family, FontFamilyType},
|
||||
};
|
||||
|
||||
/// Returns a string to be used as the `font-family` property in css.
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn build_font_family_string(
|
||||
options: NextFontLocalOptionsVc,
|
||||
font_fallbacks: FontFallbacksVc,
|
||||
request_hash: U32Vc,
|
||||
) -> Result<StringVc> {
|
||||
options: Vc<NextFontLocalOptions>,
|
||||
font_fallbacks: Vc<FontFallbacks>,
|
||||
request_hash: Vc<u32>,
|
||||
) -> Result<Vc<String>> {
|
||||
let mut font_families = vec![format!(
|
||||
"'{}'",
|
||||
*get_scoped_font_family(
|
||||
|
@ -36,5 +36,5 @@ pub(super) async fn build_font_family_string(
|
|||
}
|
||||
}
|
||||
|
||||
Ok(StringVc::cell(font_families.join(", ")))
|
||||
Ok(Vc::cell(font_families.join(", ")))
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
use anyhow::Result;
|
||||
use indoc::formatdoc;
|
||||
use turbopack_binding::turbo::tasks::primitives::StringVc;
|
||||
use turbo_tasks::Vc;
|
||||
|
||||
use super::{
|
||||
font_fallback::{FontFallback, FontFallbacksVc},
|
||||
util::FontCssPropertiesVc,
|
||||
font_fallback::{FontFallback, FontFallbacks},
|
||||
util::FontCssProperties,
|
||||
};
|
||||
|
||||
/// Builds `@font-face` stylesheet definition for a given FontFallback
|
||||
#[turbo_tasks::function]
|
||||
pub(crate) async fn build_fallback_definition(fallbacks: FontFallbacksVc) -> Result<StringVc> {
|
||||
pub(crate) async fn build_fallback_definition(fallbacks: Vc<FontFallbacks>) -> Result<Vc<String>> {
|
||||
let mut res = "".to_owned();
|
||||
for fallback_vc in &*fallbacks.await? {
|
||||
if let FontFallback::Automatic(fallback) = &*fallback_vc.await? {
|
||||
|
@ -46,13 +46,13 @@ pub(crate) async fn build_fallback_definition(fallbacks: FontFallbacksVc) -> Res
|
|||
}
|
||||
}
|
||||
|
||||
Ok(StringVc::cell(res))
|
||||
Ok(Vc::cell(res))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub(super) async fn build_font_class_rules(
|
||||
css_properties: FontCssPropertiesVc,
|
||||
) -> Result<StringVc> {
|
||||
css_properties: Vc<FontCssProperties>,
|
||||
) -> Result<Vc<String>> {
|
||||
let css_properties = &*css_properties.await?;
|
||||
let font_family_string = &*css_properties.font_family.await?;
|
||||
|
||||
|
@ -90,7 +90,7 @@ pub(super) async fn build_font_class_rules(
|
|||
))
|
||||
}
|
||||
|
||||
Ok(StringVc::cell(rules))
|
||||
Ok(Vc::cell(rules))
|
||||
}
|
||||
|
||||
fn format_fixed_percentage(value: f64) -> String {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use anyhow::{Context, Result};
|
||||
use turbo_tasks::primitives::{OptionStringVc, StringVc, U32Vc};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_hash::hash_xxh3_hash64, turbopack::core::resolve::pattern::QueryMapVc,
|
||||
turbo::tasks_hash::hash_xxh3_hash64, turbopack::core::resolve::pattern::QueryMap,
|
||||
};
|
||||
|
||||
/// CSS properties and values for a given font variation. These are rendered as
|
||||
|
@ -9,17 +9,17 @@ use turbopack_binding::{
|
|||
/// module.
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub(crate) struct FontCssProperties {
|
||||
pub font_family: StringVc,
|
||||
pub weight: OptionStringVc,
|
||||
pub style: OptionStringVc,
|
||||
pub variable: OptionStringVc,
|
||||
pub font_family: Vc<String>,
|
||||
pub weight: Vc<Option<String>>,
|
||||
pub style: Vc<Option<String>>,
|
||||
pub variable: Vc<Option<String>>,
|
||||
}
|
||||
|
||||
/// A hash of the requested querymap derived from how the user invoked
|
||||
/// next/font. Used to uniquely identify font requests for generated filenames
|
||||
/// and scoped font family names.
|
||||
#[turbo_tasks::function]
|
||||
pub(crate) async fn get_request_hash(query_vc: QueryMapVc) -> Result<U32Vc> {
|
||||
pub(crate) async fn get_request_hash(query_vc: Vc<QueryMap>) -> Result<Vc<u32>> {
|
||||
let query = &*query_vc.await?;
|
||||
let query = query.as_ref().context("Query map must be present")?;
|
||||
let mut to_hash = vec![];
|
||||
|
@ -28,7 +28,7 @@ pub(crate) async fn get_request_hash(query_vc: QueryMapVc) -> Result<U32Vc> {
|
|||
to_hash.push(v);
|
||||
}
|
||||
|
||||
Ok(U32Vc::cell(
|
||||
Ok(Vc::cell(
|
||||
// Truncate the hash to u32. These hashes are ultimately displayed as 6- or 8-character
|
||||
// hexadecimal values.
|
||||
hash_xxh3_hash64(to_hash) as u32,
|
||||
|
@ -48,10 +48,10 @@ pub(crate) enum FontFamilyType {
|
|||
/// * `request_hash` - The hash value of the font request
|
||||
#[turbo_tasks::function]
|
||||
pub(crate) async fn get_scoped_font_family(
|
||||
ty: FontFamilyTypeVc,
|
||||
font_family_name: StringVc,
|
||||
request_hash: U32Vc,
|
||||
) -> Result<StringVc> {
|
||||
ty: Vc<FontFamilyType>,
|
||||
font_family_name: Vc<String>,
|
||||
request_hash: Vc<u32>,
|
||||
) -> Result<Vc<String>> {
|
||||
let hash = {
|
||||
let mut hash = format!("{:x?}", request_hash.await?);
|
||||
hash.truncate(6);
|
||||
|
@ -64,13 +64,13 @@ pub(crate) async fn get_scoped_font_family(
|
|||
FontFamilyType::Fallback => format!("{}_Fallback", font_family_base),
|
||||
};
|
||||
|
||||
Ok(StringVc::cell(format!("__{}_{}", font_family_name, hash)))
|
||||
Ok(Vc::cell(format!("__{}_{}", font_family_name, hash)))
|
||||
}
|
||||
|
||||
/// Returns a [[StringVc]] uniquely identifying the request for the font.
|
||||
/// Returns a [[Vc<String>]] uniquely identifying the request for the font.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_request_id(font_family: StringVc, request_hash: U32Vc) -> Result<StringVc> {
|
||||
Ok(StringVc::cell(format!(
|
||||
pub async fn get_request_id(font_family: Vc<String>, request_hash: Vc<u32>) -> Result<Vc<String>> {
|
||||
Ok(Vc::cell(format!(
|
||||
"{}_{:x?}",
|
||||
font_family.await?.to_lowercase().replace(' ', "_"),
|
||||
request_hash.await?
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::{primitives::StringVc, Value};
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbo_tasks_fs::FileSystem;
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
asset::AssetContent,
|
||||
ident::AssetIdentVc,
|
||||
introspect::{Introspectable, IntrospectableVc},
|
||||
server_fs::ServerFileSystemVc,
|
||||
version::VersionedContent,
|
||||
asset::AssetContent, ident::AssetIdent, introspect::Introspectable,
|
||||
server_fs::ServerFileSystem, version::VersionedContent,
|
||||
},
|
||||
dev_server::source::{
|
||||
query::QueryValue,
|
||||
route_tree::{RouteTreeVc, RouteType},
|
||||
wrapping_source::{
|
||||
ContentSourceProcessor, ContentSourceProcessorVc, WrappedGetContentSourceContentVc,
|
||||
},
|
||||
ContentSource, ContentSourceContent, ContentSourceContentVc, ContentSourceData,
|
||||
ContentSourceDataFilter, ContentSourceDataVary, ContentSourceDataVaryVc, ContentSourceVc,
|
||||
GetContentSourceContent, GetContentSourceContentVc, GetContentSourceContentsVc,
|
||||
ProxyResult, RewriteBuilder,
|
||||
route_tree::{RouteTree, RouteType},
|
||||
wrapping_source::{ContentSourceProcessor, WrappedGetContentSourceContent},
|
||||
ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataFilter,
|
||||
ContentSourceDataVary, GetContentSourceContent, ProxyResult, RewriteBuilder,
|
||||
},
|
||||
image::process::optimize,
|
||||
};
|
||||
|
@ -27,13 +20,13 @@ use turbopack_binding::turbopack::{
|
|||
/// next/image.
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextImageContentSource {
|
||||
asset_source: ContentSourceVc,
|
||||
asset_source: Vc<Box<dyn ContentSource>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextImageContentSourceVc {
|
||||
impl NextImageContentSource {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(asset_source: ContentSourceVc) -> NextImageContentSourceVc {
|
||||
pub fn new(asset_source: Vc<Box<dyn ContentSource>>) -> Vc<NextImageContentSource> {
|
||||
NextImageContentSource { asset_source }.cell()
|
||||
}
|
||||
}
|
||||
|
@ -41,15 +34,15 @@ impl NextImageContentSourceVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ContentSource for NextImageContentSource {
|
||||
#[turbo_tasks::function]
|
||||
fn get_routes(self_vc: NextImageContentSourceVc) -> RouteTreeVc {
|
||||
RouteTreeVc::new_route(Vec::new(), RouteType::Exact, self_vc.into())
|
||||
fn get_routes(self: Vc<Self>) -> Vc<RouteTree> {
|
||||
RouteTree::new_route(Vec::new(), RouteType::Exact, Vc::upcast(self))
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl GetContentSourceContent for NextImageContentSource {
|
||||
#[turbo_tasks::function]
|
||||
async fn vary(&self) -> ContentSourceDataVaryVc {
|
||||
async fn vary(&self) -> Vc<ContentSourceDataVary> {
|
||||
ContentSourceDataVary {
|
||||
query: Some(ContentSourceDataFilter::Subset(
|
||||
["url".to_string(), "w".to_string(), "q".to_string()].into(),
|
||||
|
@ -61,11 +54,11 @@ impl GetContentSourceContent for NextImageContentSource {
|
|||
|
||||
#[turbo_tasks::function]
|
||||
async fn get(
|
||||
self_vc: NextImageContentSourceVc,
|
||||
_path: &str,
|
||||
self: Vc<Self>,
|
||||
_path: String,
|
||||
data: Value<ContentSourceData>,
|
||||
) -> Result<ContentSourceContentVc> {
|
||||
let this = self_vc.await?;
|
||||
) -> Result<Vc<ContentSourceContent>> {
|
||||
let this = self.await?;
|
||||
|
||||
let Some(query) = &data.query else {
|
||||
bail!("missing query");
|
||||
|
@ -99,18 +92,17 @@ impl GetContentSourceContent for NextImageContentSource {
|
|||
// TODO: re-encode into next-gen formats.
|
||||
|
||||
if let Some(path) = url.strip_prefix('/') {
|
||||
let sources = this.asset_source.get_routes().get(path).await?;
|
||||
let sources = this.asset_source.get_routes().get(path.to_string()).await?;
|
||||
let sources = sources
|
||||
.iter()
|
||||
.map(|s| {
|
||||
WrappedGetContentSourceContentVc::new(
|
||||
Vc::upcast(WrappedGetContentSourceContent::new(
|
||||
*s,
|
||||
NextImageContentSourceProcessorVc::new(path.to_string(), w, q).into(),
|
||||
)
|
||||
.into()
|
||||
Vc::upcast(NextImageContentSourceProcessor::new(path.to_string(), w, q)),
|
||||
))
|
||||
})
|
||||
.collect();
|
||||
let sources = GetContentSourceContentsVc::cell(sources);
|
||||
let sources = Vc::cell(sources);
|
||||
return Ok(
|
||||
ContentSourceContent::Rewrite(RewriteBuilder::new_sources(sources).build()).cell(),
|
||||
);
|
||||
|
@ -132,13 +124,13 @@ impl GetContentSourceContent for NextImageContentSource {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Introspectable for NextImageContentSource {
|
||||
#[turbo_tasks::function]
|
||||
fn ty(&self) -> StringVc {
|
||||
StringVc::cell("next image content source".to_string())
|
||||
fn ty(&self) -> Vc<String> {
|
||||
Vc::cell("next image content source".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn details(&self) -> StringVc {
|
||||
StringVc::cell("supports dynamic serving of any statically imported image".to_string())
|
||||
fn details(&self) -> Vc<String> {
|
||||
Vc::cell("supports dynamic serving of any statically imported image".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,9 +142,9 @@ struct NextImageContentSourceProcessor {
|
|||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextImageContentSourceProcessorVc {
|
||||
impl NextImageContentSourceProcessor {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(path: String, width: u32, quality: u8) -> NextImageContentSourceProcessorVc {
|
||||
pub fn new(path: String, width: u32, quality: u8) -> Vc<NextImageContentSourceProcessor> {
|
||||
NextImageContentSourceProcessor {
|
||||
path,
|
||||
width,
|
||||
|
@ -165,7 +157,7 @@ impl NextImageContentSourceProcessorVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ContentSourceProcessor for NextImageContentSourceProcessor {
|
||||
#[turbo_tasks::function]
|
||||
async fn process(&self, content: ContentSourceContentVc) -> Result<ContentSourceContentVc> {
|
||||
async fn process(&self, content: Vc<ContentSourceContent>) -> Result<Vc<ContentSourceContent>> {
|
||||
let ContentSourceContent::Static(static_content) = *content.await? else {
|
||||
return Ok(content);
|
||||
};
|
||||
|
@ -175,13 +167,13 @@ impl ContentSourceProcessor for NextImageContentSourceProcessor {
|
|||
return Ok(content);
|
||||
};
|
||||
let optimized_file_content = optimize(
|
||||
AssetIdentVc::from_path(ServerFileSystemVc::new().root().join(&self.path)),
|
||||
AssetIdent::from_path(ServerFileSystem::new().root().join(self.path.clone())),
|
||||
file_content,
|
||||
self.width,
|
||||
u32::MAX,
|
||||
self.quality,
|
||||
);
|
||||
Ok(ContentSourceContentVc::static_content(
|
||||
Ok(ContentSourceContent::static_content(
|
||||
AssetContent::File(optimized_file_content).into(),
|
||||
))
|
||||
}
|
||||
|
|
|
@ -2,5 +2,5 @@ pub(crate) mod content_source;
|
|||
pub(crate) mod module;
|
||||
pub(crate) mod source_asset;
|
||||
|
||||
pub use content_source::NextImageContentSourceVc;
|
||||
pub use module::StructuredImageModuleTypeVc;
|
||||
pub use content_source::NextImageContentSource;
|
||||
pub use module::StructuredImageModuleType;
|
||||
|
|
|
@ -1,20 +1,14 @@
|
|||
use anyhow::Result;
|
||||
use indexmap::indexmap;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::tasks::Value,
|
||||
turbopack::{
|
||||
core::{
|
||||
context::AssetContext,
|
||||
module::ModuleVc,
|
||||
reference_type::{InnerAssetsVc, ReferenceType},
|
||||
resolve::ModulePartVc,
|
||||
source::SourceVc,
|
||||
},
|
||||
r#static::StaticModuleAssetVc,
|
||||
turbopack::{
|
||||
module_options::{CustomModuleType, CustomModuleTypeVc},
|
||||
ModuleAssetContextVc,
|
||||
context::AssetContext, module::Module, reference_type::ReferenceType,
|
||||
resolve::ModulePart, source::Source,
|
||||
},
|
||||
r#static::StaticModuleAsset,
|
||||
turbopack::{module_options::CustomModuleType, ModuleAssetContext},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -45,30 +39,31 @@ pub struct StructuredImageModuleType {
|
|||
|
||||
impl StructuredImageModuleType {
|
||||
pub(crate) fn create_module(
|
||||
source: SourceVc,
|
||||
source: Vc<Box<dyn Source>>,
|
||||
blur_placeholder_mode: BlurPlaceholderMode,
|
||||
context: ModuleAssetContextVc,
|
||||
) -> ModuleVc {
|
||||
let static_asset = StaticModuleAssetVc::new(source, context.into());
|
||||
context: Vc<ModuleAssetContext>,
|
||||
) -> Vc<Box<dyn Module>> {
|
||||
let static_asset = StaticModuleAsset::new(source, Vc::upcast(context));
|
||||
context.process(
|
||||
StructuredImageFileSource {
|
||||
image: source,
|
||||
blur_placeholder_mode,
|
||||
}
|
||||
.cell()
|
||||
.into(),
|
||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap!(
|
||||
"IMAGE".to_string() => static_asset.into()
|
||||
Vc::upcast(
|
||||
StructuredImageFileSource {
|
||||
image: source,
|
||||
blur_placeholder_mode,
|
||||
}
|
||||
.cell(),
|
||||
),
|
||||
Value::new(ReferenceType::Internal(Vc::cell(indexmap!(
|
||||
"IMAGE".to_string() => Vc::upcast(static_asset)
|
||||
)))),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl StructuredImageModuleTypeVc {
|
||||
impl StructuredImageModuleType {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(blur_placeholder_mode: Value<BlurPlaceholderMode>) -> Self {
|
||||
StructuredImageModuleTypeVc::cell(StructuredImageModuleType {
|
||||
pub fn new(blur_placeholder_mode: Value<BlurPlaceholderMode>) -> Vc<Self> {
|
||||
StructuredImageModuleType::cell(StructuredImageModuleType {
|
||||
blur_placeholder_mode: blur_placeholder_mode.into_value(),
|
||||
})
|
||||
}
|
||||
|
@ -79,10 +74,10 @@ impl CustomModuleType for StructuredImageModuleType {
|
|||
#[turbo_tasks::function]
|
||||
fn create_module(
|
||||
&self,
|
||||
source: SourceVc,
|
||||
context: ModuleAssetContextVc,
|
||||
_part: Option<ModulePartVc>,
|
||||
) -> ModuleVc {
|
||||
source: Vc<Box<dyn Source>>,
|
||||
context: Vc<ModuleAssetContext>,
|
||||
_part: Option<Vc<ModulePart>>,
|
||||
) -> Vc<Box<dyn Module>> {
|
||||
StructuredImageModuleType::create_module(source, self.blur_placeholder_mode, context)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
use std::io::Write;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::{
|
||||
tasks::primitives::StringVc,
|
||||
tasks_fs::{rope::RopeBuilder, FileContent},
|
||||
},
|
||||
turbo::tasks_fs::{rope::RopeBuilder, FileContent},
|
||||
turbopack::{
|
||||
core::{
|
||||
asset::{Asset, AssetContent, AssetContentVc, AssetVc},
|
||||
ident::AssetIdentVc,
|
||||
source::{Source, SourceVc},
|
||||
asset::{Asset, AssetContent},
|
||||
ident::AssetIdent,
|
||||
source::Source,
|
||||
},
|
||||
ecmascript::utils::StringifyJs,
|
||||
image::process::{get_meta_data, BlurPlaceholderOptions, BlurPlaceholderOptionsVc},
|
||||
image::process::{get_meta_data, BlurPlaceholderOptions},
|
||||
},
|
||||
};
|
||||
|
||||
use super::module::BlurPlaceholderMode;
|
||||
|
||||
fn modifier() -> StringVc {
|
||||
StringVc::cell("structured image object".to_string())
|
||||
fn modifier() -> Vc<String> {
|
||||
Vc::cell("structured image object".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn blur_options() -> BlurPlaceholderOptionsVc {
|
||||
fn blur_options() -> Vc<BlurPlaceholderOptions> {
|
||||
BlurPlaceholderOptions {
|
||||
quality: 70,
|
||||
size: 8,
|
||||
|
@ -36,7 +34,7 @@ fn blur_options() -> BlurPlaceholderOptionsVc {
|
|||
/// an object with meta information like width, height and a blur placeholder.
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct StructuredImageFileSource {
|
||||
pub image: SourceVc,
|
||||
pub image: Vc<Box<dyn Source>>,
|
||||
pub blur_placeholder_mode: BlurPlaceholderMode,
|
||||
}
|
||||
|
||||
|
@ -46,15 +44,15 @@ impl Source for StructuredImageFileSource {}
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Asset for StructuredImageFileSource {
|
||||
#[turbo_tasks::function]
|
||||
fn ident(&self) -> AssetIdentVc {
|
||||
fn ident(&self) -> Vc<AssetIdent> {
|
||||
self.image
|
||||
.ident()
|
||||
.with_modifier(modifier())
|
||||
.rename_as("*.mjs")
|
||||
.rename_as("*.mjs".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn content(&self) -> Result<AssetContentVc> {
|
||||
async fn content(&self) -> Result<Vc<AssetContent>> {
|
||||
let content = self.image.content().await?;
|
||||
let AssetContent::File(content) = *content else {
|
||||
bail!("Input source is not a file and can't be transformed into image information");
|
||||
|
|
|
@ -1,23 +1,20 @@
|
|||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use turbo_tasks::Value;
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::{glob::GlobVc, FileSystem, FileSystemPathVc},
|
||||
turbo::tasks_fs::{glob::Glob, FileSystem, FileSystemPath},
|
||||
turbopack::{
|
||||
core::{
|
||||
asset::Asset,
|
||||
resolve::{
|
||||
options::{
|
||||
ConditionValue, ImportMap, ImportMapVc, ImportMapping, ImportMappingVc,
|
||||
ResolveOptionsVc, ResolvedMap, ResolvedMapVc,
|
||||
},
|
||||
parse::RequestVc,
|
||||
options::{ConditionValue, ImportMap, ImportMapping, ResolveOptions, ResolvedMap},
|
||||
parse::Request,
|
||||
pattern::Pattern,
|
||||
resolve, AliasPattern, ResolveAliasMapVc, SubpathValue,
|
||||
resolve, AliasPattern, ResolveAliasMap, SubpathValue,
|
||||
},
|
||||
},
|
||||
node::execution_context::ExecutionContextVc,
|
||||
node::execution_context::ExecutionContext,
|
||||
turbopack::{resolve_options, resolve_options_context::ResolveOptionsContext},
|
||||
},
|
||||
};
|
||||
|
@ -26,10 +23,10 @@ use crate::{
|
|||
embed_js::{next_js_fs, VIRTUAL_PACKAGE_NAME},
|
||||
mode::NextMode,
|
||||
next_client::context::ClientContextType,
|
||||
next_config::NextConfigVc,
|
||||
next_config::NextConfig,
|
||||
next_font::{
|
||||
google::{NextFontGoogleCssModuleReplacerVc, NextFontGoogleReplacerVc},
|
||||
local::{NextFontLocalCssModuleReplacerVc, NextFontLocalReplacerVc},
|
||||
google::{NextFontGoogleCssModuleReplacer, NextFontGoogleReplacer},
|
||||
local::{NextFontLocalCssModuleReplacer, NextFontLocalReplacer},
|
||||
},
|
||||
next_server::context::ServerContextType,
|
||||
};
|
||||
|
@ -38,11 +35,11 @@ use crate::{
|
|||
/// Computes the Next-specific client import map.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_next_client_import_map(
|
||||
project_path: FileSystemPathVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
ty: Value<ClientContextType>,
|
||||
next_config: NextConfigVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
) -> Result<ImportMapVc> {
|
||||
next_config: Vc<NextConfig>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
) -> Result<Vc<ImportMap>> {
|
||||
let mut import_map = ImportMap::empty();
|
||||
|
||||
insert_next_shared_aliases(
|
||||
|
@ -139,7 +136,7 @@ pub async fn get_next_client_import_map(
|
|||
|
||||
/// Computes the Next-specific client import map.
|
||||
#[turbo_tasks::function]
|
||||
pub fn get_next_build_import_map() -> ImportMapVc {
|
||||
pub fn get_next_build_import_map() -> Vc<ImportMap> {
|
||||
let mut import_map = ImportMap::empty();
|
||||
|
||||
insert_package_alias(
|
||||
|
@ -161,7 +158,7 @@ pub fn get_next_build_import_map() -> ImportMapVc {
|
|||
/// Computes the Next-specific client fallback import map, which provides
|
||||
/// polyfills to Node.js externals.
|
||||
#[turbo_tasks::function]
|
||||
pub fn get_next_client_fallback_import_map(ty: Value<ClientContextType>) -> ImportMapVc {
|
||||
pub fn get_next_client_fallback_import_map(ty: Value<ClientContextType>) -> Vc<ImportMap> {
|
||||
let mut import_map = ImportMap::empty();
|
||||
|
||||
match ty.into_value() {
|
||||
|
@ -188,12 +185,12 @@ pub fn get_next_client_fallback_import_map(ty: Value<ClientContextType>) -> Impo
|
|||
/// Computes the Next-specific server-side import map.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_next_server_import_map(
|
||||
project_path: FileSystemPathVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
ty: Value<ServerContextType>,
|
||||
mode: NextMode,
|
||||
next_config: NextConfigVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
) -> Result<ImportMapVc> {
|
||||
next_config: Vc<NextConfig>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
) -> Result<Vc<ImportMap>> {
|
||||
let mut import_map = ImportMap::empty();
|
||||
|
||||
insert_next_shared_aliases(
|
||||
|
@ -253,12 +250,12 @@ pub async fn get_next_server_import_map(
|
|||
/// Computes the Next-specific edge-side import map.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_next_edge_import_map(
|
||||
project_path: FileSystemPathVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
ty: Value<ServerContextType>,
|
||||
mode: NextMode,
|
||||
next_config: NextConfigVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
) -> Result<ImportMapVc> {
|
||||
next_config: Vc<NextConfig>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
) -> Result<Vc<ImportMap>> {
|
||||
let mut import_map = ImportMap::empty();
|
||||
|
||||
insert_next_shared_aliases(
|
||||
|
@ -302,14 +299,17 @@ pub async fn get_next_edge_import_map(
|
|||
}
|
||||
|
||||
pub fn get_next_client_resolved_map(
|
||||
context: FileSystemPathVc,
|
||||
root: FileSystemPathVc,
|
||||
) -> ResolvedMapVc {
|
||||
context: Vc<FileSystemPath>,
|
||||
root: Vc<FileSystemPath>,
|
||||
) -> Vc<ResolvedMap> {
|
||||
let glob_mappings = vec![
|
||||
// Temporary hack to replace the hot reloader until this is passable by props in next.js
|
||||
(
|
||||
context.root(),
|
||||
GlobVc::new("**/next/dist/client/components/react-dev-overlay/hot-reloader-client.js"),
|
||||
Glob::new(
|
||||
"**/next/dist/client/components/react-dev-overlay/hot-reloader-client.js"
|
||||
.to_string(),
|
||||
),
|
||||
ImportMapping::PrimaryAlternative(
|
||||
"@vercel/turbopack-next/dev/hot-reloader.tsx".to_string(),
|
||||
Some(root),
|
||||
|
@ -515,9 +515,9 @@ pub fn mdx_import_source_file() -> String {
|
|||
// Make sure to not add any external requests here.
|
||||
pub async fn insert_next_shared_aliases(
|
||||
import_map: &mut ImportMap,
|
||||
project_path: FileSystemPathVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
next_config: NextConfigVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
next_config: Vc<NextConfig>,
|
||||
) -> Result<()> {
|
||||
let package_root = next_js_fs().root();
|
||||
|
||||
|
@ -549,38 +549,42 @@ pub async fn insert_next_shared_aliases(
|
|||
import_map.insert_alias(
|
||||
// Request path from js via next-font swc transform
|
||||
AliasPattern::exact("next/font/google/target.css"),
|
||||
ImportMapping::Dynamic(NextFontGoogleReplacerVc::new(project_path).into()).into(),
|
||||
ImportMapping::Dynamic(Vc::upcast(NextFontGoogleReplacer::new(project_path))).into(),
|
||||
);
|
||||
|
||||
import_map.insert_alias(
|
||||
// Request path from js via next-font swc transform
|
||||
AliasPattern::exact("@next/font/google/target.css"),
|
||||
ImportMapping::Dynamic(NextFontGoogleReplacerVc::new(project_path).into()).into(),
|
||||
ImportMapping::Dynamic(Vc::upcast(NextFontGoogleReplacer::new(project_path))).into(),
|
||||
);
|
||||
|
||||
import_map.insert_alias(
|
||||
AliasPattern::exact("@vercel/turbopack-next/internal/font/google/cssmodule.module.css"),
|
||||
ImportMapping::Dynamic(
|
||||
NextFontGoogleCssModuleReplacerVc::new(project_path, execution_context).into(),
|
||||
)
|
||||
ImportMapping::Dynamic(Vc::upcast(NextFontGoogleCssModuleReplacer::new(
|
||||
project_path,
|
||||
execution_context,
|
||||
)))
|
||||
.into(),
|
||||
);
|
||||
|
||||
import_map.insert_alias(
|
||||
// Request path from js via next-font swc transform
|
||||
AliasPattern::exact("next/font/local/target.css"),
|
||||
ImportMapping::Dynamic(NextFontLocalReplacerVc::new(project_path).into()).into(),
|
||||
ImportMapping::Dynamic(Vc::upcast(NextFontLocalReplacer::new(project_path))).into(),
|
||||
);
|
||||
|
||||
import_map.insert_alias(
|
||||
// Request path from js via next-font swc transform
|
||||
AliasPattern::exact("@next/font/local/target.css"),
|
||||
ImportMapping::Dynamic(NextFontLocalReplacerVc::new(project_path).into()).into(),
|
||||
ImportMapping::Dynamic(Vc::upcast(NextFontLocalReplacer::new(project_path))).into(),
|
||||
);
|
||||
|
||||
import_map.insert_alias(
|
||||
AliasPattern::exact("@vercel/turbopack-next/internal/font/local/cssmodule.module.css"),
|
||||
ImportMapping::Dynamic(NextFontLocalCssModuleReplacerVc::new(project_path).into()).into(),
|
||||
ImportMapping::Dynamic(Vc::upcast(NextFontLocalCssModuleReplacer::new(
|
||||
project_path,
|
||||
)))
|
||||
.into(),
|
||||
);
|
||||
|
||||
import_map.insert_singleton_alias("@swc/helpers", get_next_package(project_path));
|
||||
|
@ -601,8 +605,8 @@ pub async fn insert_next_shared_aliases(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
async fn package_lookup_resolve_options(
|
||||
project_path: FileSystemPathVc,
|
||||
) -> Result<ResolveOptionsVc> {
|
||||
project_path: Vc<FileSystemPath>,
|
||||
) -> Result<Vc<ResolveOptions>> {
|
||||
Ok(resolve_options(
|
||||
project_path,
|
||||
ResolveOptionsContext {
|
||||
|
@ -616,10 +620,10 @@ async fn package_lookup_resolve_options(
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_next_package(project_path: FileSystemPathVc) -> Result<FileSystemPathVc> {
|
||||
pub async fn get_next_package(project_path: Vc<FileSystemPath>) -> Result<Vc<FileSystemPath>> {
|
||||
let result = resolve(
|
||||
project_path,
|
||||
RequestVc::parse(Value::new(Pattern::Constant(
|
||||
Request::parse(Value::new(Pattern::Constant(
|
||||
"next/package.json".to_string(),
|
||||
))),
|
||||
package_lookup_resolve_options(project_path),
|
||||
|
@ -631,8 +635,8 @@ pub async fn get_next_package(project_path: FileSystemPathVc) -> Result<FileSyst
|
|||
|
||||
pub async fn insert_alias_option<const N: usize>(
|
||||
import_map: &mut ImportMap,
|
||||
project_path: FileSystemPathVc,
|
||||
alias_options: ResolveAliasMapVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
alias_options: Vc<ResolveAliasMap>,
|
||||
conditions: [&'static str; N],
|
||||
) -> Result<()> {
|
||||
let conditions = BTreeMap::from(conditions.map(|c| (c.to_string(), ConditionValue::Set)));
|
||||
|
@ -647,8 +651,8 @@ pub async fn insert_alias_option<const N: usize>(
|
|||
fn export_value_to_import_mapping(
|
||||
value: &SubpathValue,
|
||||
conditions: &BTreeMap<String, ConditionValue>,
|
||||
project_path: FileSystemPathVc,
|
||||
) -> Option<ImportMappingVc> {
|
||||
project_path: Vc<FileSystemPath>,
|
||||
) -> Option<Vc<ImportMapping>> {
|
||||
let mut result = Vec::new();
|
||||
value.add_results(
|
||||
conditions,
|
||||
|
@ -679,13 +683,17 @@ fn export_value_to_import_mapping(
|
|||
fn insert_alias_to_alternatives<'a>(
|
||||
import_map: &mut ImportMap,
|
||||
alias: impl Into<String> + 'a,
|
||||
alternatives: Vec<ImportMappingVc>,
|
||||
alternatives: Vec<Vc<ImportMapping>>,
|
||||
) {
|
||||
import_map.insert_exact_alias(alias, ImportMapping::Alternatives(alternatives).into());
|
||||
}
|
||||
|
||||
/// Inserts an alias to an import mapping into an import map.
|
||||
fn insert_package_alias(import_map: &mut ImportMap, prefix: &str, package_root: FileSystemPathVc) {
|
||||
fn insert_package_alias(
|
||||
import_map: &mut ImportMap,
|
||||
prefix: &str,
|
||||
package_root: Vc<FileSystemPath>,
|
||||
) {
|
||||
import_map.insert_wildcard_alias(
|
||||
prefix,
|
||||
ImportMapping::PrimaryAlternative("./*".to_string(), Some(package_root)).cell(),
|
||||
|
@ -703,12 +711,12 @@ 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: FileSystemPathVc, request: &str) -> ImportMappingVc {
|
||||
fn request_to_import_mapping(context_path: Vc<FileSystemPath>, request: &str) -> Vc<ImportMapping> {
|
||||
ImportMapping::PrimaryAlternative(request.to_string(), 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) -> ImportMappingVc {
|
||||
fn external_request_to_import_mapping(request: &str) -> Vc<ImportMapping> {
|
||||
ImportMapping::External(Some(request.to_string())).into()
|
||||
}
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks::primitives::BoolVc,
|
||||
turbopack::node::route_matcher::{ParamsVc, RouteMatcher},
|
||||
};
|
||||
use turbopack_binding::turbopack::node::route_matcher::{Params, RouteMatcherRef};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub struct AllMatch;
|
||||
|
||||
impl RouteMatcher for AllMatch {
|
||||
fn matches(&self, _path: &str) -> BoolVc {
|
||||
BoolVc::cell(true)
|
||||
impl RouteMatcherRef for AllMatch {
|
||||
fn matches(&self, _path: &str) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn params(&self, _path: &str) -> ParamsVc {
|
||||
ParamsVc::cell(Some(Default::default()))
|
||||
fn params(&self, _path: &str) -> Params {
|
||||
Params(Some(Default::default()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use anyhow::{bail, Result};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks::primitives::{BoolVc, StringVc},
|
||||
turbopack::node::route_matcher::{ParamsVc, RouteMatcher, RouteMatcherVc},
|
||||
};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::node::route_matcher::{Params, RouteMatcher, RouteMatcherRef};
|
||||
|
||||
use self::{
|
||||
all::AllMatch,
|
||||
|
@ -17,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: StringVc,
|
||||
path: Vc<String>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextExactMatcherVc {
|
||||
impl NextExactMatcher {
|
||||
#[turbo_tasks::function]
|
||||
pub async fn new(path: StringVc) -> Result<Self> {
|
||||
pub async fn new(path: Vc<String>) -> Result<Vc<Self>> {
|
||||
Ok(Self::cell(NextExactMatcher { path }))
|
||||
}
|
||||
}
|
||||
|
@ -31,13 +29,13 @@ impl NextExactMatcherVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl RouteMatcher for NextExactMatcher {
|
||||
#[turbo_tasks::function]
|
||||
async fn matches(&self, path: &str) -> Result<BoolVc> {
|
||||
Ok(BoolVc::cell(path == *self.path.await?))
|
||||
async fn matches(&self, path: String) -> Result<Vc<bool>> {
|
||||
Ok(Vc::cell(path == *self.path.await?))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn params(&self, path: &str) -> Result<ParamsVc> {
|
||||
Ok(ParamsVc::cell(if path == *self.path.await? {
|
||||
async fn params(&self, path: String) -> Result<Vc<Params>> {
|
||||
Ok(Vc::cell(if path == *self.path.await? {
|
||||
Some(Default::default())
|
||||
} else {
|
||||
None
|
||||
|
@ -53,9 +51,9 @@ pub(crate) struct NextParamsMatcher {
|
|||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextParamsMatcherVc {
|
||||
impl NextParamsMatcher {
|
||||
#[turbo_tasks::function]
|
||||
pub async fn new(path: StringVc) -> Result<Self> {
|
||||
pub async fn new(path: Vc<String>) -> Result<Vc<Self>> {
|
||||
Ok(Self::cell(NextParamsMatcher {
|
||||
matcher: build_path_regex(path.await?.as_str())?,
|
||||
}))
|
||||
|
@ -65,13 +63,13 @@ impl NextParamsMatcherVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl RouteMatcher for NextParamsMatcher {
|
||||
#[turbo_tasks::function]
|
||||
fn matches(&self, path: &str) -> BoolVc {
|
||||
self.matcher.matches(path)
|
||||
fn matches(&self, path: String) -> Vc<bool> {
|
||||
Vc::cell(self.matcher.matches(&path))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn params(&self, path: &str) -> ParamsVc {
|
||||
self.matcher.params(path)
|
||||
fn params(&self, path: String) -> Vc<Params> {
|
||||
Params::cell(self.matcher.params(&path))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,11 +82,11 @@ pub(crate) struct NextPrefixSuffixParamsMatcher {
|
|||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextPrefixSuffixParamsMatcherVc {
|
||||
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: StringVc, prefix: &str, suffix: &str) -> Result<Self> {
|
||||
pub async fn new(path: Vc<String>, prefix: String, suffix: String) -> Result<Vc<Self>> {
|
||||
Ok(Self::cell(NextPrefixSuffixParamsMatcher {
|
||||
matcher: PrefixSuffixMatcher::new(
|
||||
prefix.to_string(),
|
||||
|
@ -102,13 +100,13 @@ impl NextPrefixSuffixParamsMatcherVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl RouteMatcher for NextPrefixSuffixParamsMatcher {
|
||||
#[turbo_tasks::function]
|
||||
fn matches(&self, path: &str) -> BoolVc {
|
||||
self.matcher.matches(path)
|
||||
fn matches(&self, path: String) -> Vc<bool> {
|
||||
Vc::cell(self.matcher.matches(&path))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn params(&self, path: &str) -> ParamsVc {
|
||||
self.matcher.params(path)
|
||||
fn params(&self, path: String) -> Vc<Params> {
|
||||
Params::cell(self.matcher.params(&path))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,9 +118,9 @@ pub(crate) struct NextFallbackMatcher {
|
|||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextFallbackMatcherVc {
|
||||
impl NextFallbackMatcher {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new() -> Self {
|
||||
pub fn new() -> Vc<Self> {
|
||||
Self::cell(NextFallbackMatcher { matcher: AllMatch })
|
||||
}
|
||||
}
|
||||
|
@ -130,13 +128,13 @@ impl NextFallbackMatcherVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl RouteMatcher for NextFallbackMatcher {
|
||||
#[turbo_tasks::function]
|
||||
fn matches(&self, path: &str) -> BoolVc {
|
||||
self.matcher.matches(path)
|
||||
fn matches(&self, path: String) -> Vc<bool> {
|
||||
Vc::cell(self.matcher.matches(&path))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn params(&self, path: &str) -> ParamsVc {
|
||||
self.matcher.params(path)
|
||||
fn params(&self, path: String) -> Vc<Params> {
|
||||
Params::cell(self.matcher.params(&path))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use anyhow::{Context, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks::primitives::{BoolVc, Regex},
|
||||
turbopack::node::route_matcher::{Param, ParamsVc, RouteMatcher},
|
||||
turbo::tasks::primitives::Regex,
|
||||
turbopack::node::route_matcher::{Param, Params, RouteMatcherRef},
|
||||
};
|
||||
|
||||
/// A regular expression that matches a path, with named capture groups for the
|
||||
|
@ -31,13 +31,13 @@ impl std::fmt::Display for PathRegex {
|
|||
}
|
||||
}
|
||||
|
||||
impl RouteMatcher for PathRegex {
|
||||
fn matches(&self, path: &str) -> BoolVc {
|
||||
BoolVc::cell(self.regex.is_match(path))
|
||||
impl RouteMatcherRef for PathRegex {
|
||||
fn matches(&self, path: &str) -> bool {
|
||||
self.regex.is_match(path)
|
||||
}
|
||||
|
||||
fn params(&self, path: &str) -> ParamsVc {
|
||||
ParamsVc::cell(self.regex.captures(path).map(|capture| {
|
||||
fn params(&self, path: &str) -> Params {
|
||||
Params(self.regex.captures(path).map(|capture| {
|
||||
self.named_params
|
||||
.iter()
|
||||
.enumerate()
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use turbopack_binding::{
|
||||
turbo::tasks::primitives::BoolVc,
|
||||
turbopack::node::route_matcher::{ParamsVc, RouteMatcher},
|
||||
};
|
||||
use turbopack_binding::turbopack::node::route_matcher::{Params, RouteMatcherRef};
|
||||
|
||||
/// A composite route matcher that matches a path if it has a given prefix and
|
||||
/// suffix.
|
||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub struct PrefixSuffixMatcher<T>
|
||||
where
|
||||
T: RouteMatcher,
|
||||
T: RouteMatcherRef,
|
||||
{
|
||||
prefix: String,
|
||||
suffix: String,
|
||||
|
@ -18,7 +15,7 @@ where
|
|||
|
||||
impl<T> PrefixSuffixMatcher<T>
|
||||
where
|
||||
T: RouteMatcher,
|
||||
T: RouteMatcherRef,
|
||||
{
|
||||
/// Creates a new [PrefixSuffixMatcher].
|
||||
pub fn new(prefix: String, suffix: String, inner: T) -> Self {
|
||||
|
@ -35,23 +32,23 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> RouteMatcher for PrefixSuffixMatcher<T>
|
||||
impl<T> RouteMatcherRef for PrefixSuffixMatcher<T>
|
||||
where
|
||||
T: RouteMatcher,
|
||||
T: RouteMatcherRef,
|
||||
{
|
||||
fn matches(&self, path: &str) -> BoolVc {
|
||||
fn matches(&self, path: &str) -> bool {
|
||||
if let Some(path) = self.strip_prefix_and_suffix(path) {
|
||||
self.inner.matches(path)
|
||||
} else {
|
||||
BoolVc::cell(false)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn params(&self, path: &str) -> ParamsVc {
|
||||
fn params(&self, path: &str) -> Params {
|
||||
if let Some(path) = self.strip_prefix_and_suffix(path) {
|
||||
self.inner.params(path)
|
||||
} else {
|
||||
ParamsVc::cell(None)
|
||||
Params(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,42 +1,38 @@
|
|||
use anyhow::Result;
|
||||
use turbo_tasks::{primitives::StringVc, Value};
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbo_tasks_fs::FileSystem;
|
||||
use turbopack_binding::{
|
||||
turbo::{tasks_env::ProcessEnvVc, tasks_fs::FileSystemPathVc},
|
||||
turbo::{tasks_env::ProcessEnv, tasks_fs::FileSystemPath},
|
||||
turbopack::{
|
||||
build::BuildChunkingContextVc,
|
||||
build::BuildChunkingContext,
|
||||
core::{
|
||||
compile_time_defines,
|
||||
compile_time_info::{
|
||||
CompileTimeDefines, CompileTimeDefinesVc, CompileTimeInfo, CompileTimeInfoVc,
|
||||
FreeVarReferencesVc,
|
||||
},
|
||||
environment::{EnvironmentVc, ExecutionEnvironment, NodeJsEnvironmentVc, ServerAddrVc},
|
||||
compile_time_info::{CompileTimeDefines, CompileTimeInfo, FreeVarReferences},
|
||||
environment::{Environment, ExecutionEnvironment, NodeJsEnvironment, ServerAddr},
|
||||
free_var_references,
|
||||
resolve::{parse::RequestVc, pattern::Pattern},
|
||||
resolve::{parse::Request, pattern::Pattern},
|
||||
},
|
||||
ecmascript::TransformPluginVc,
|
||||
ecmascript::TransformPlugin,
|
||||
ecmascript_plugin::transform::directives::{
|
||||
client::ClientDirectiveTransformer, server::ServerDirectiveTransformer,
|
||||
},
|
||||
env::ProcessEnvAssetVc,
|
||||
node::execution_context::ExecutionContextVc,
|
||||
env::ProcessEnvAsset,
|
||||
node::execution_context::ExecutionContext,
|
||||
turbopack::{
|
||||
condition::ContextCondition,
|
||||
module_options::{
|
||||
CustomEcmascriptTransformPlugins, CustomEcmascriptTransformPluginsVc,
|
||||
JsxTransformOptions, MdxTransformModuleOptions, ModuleOptionsContext,
|
||||
ModuleOptionsContextVc, PostCssTransformOptions, TypescriptTransformOptions,
|
||||
CustomEcmascriptTransformPlugins, JsxTransformOptions, MdxTransformModuleOptions,
|
||||
ModuleOptionsContext, PostCssTransformOptions, TypescriptTransformOptions,
|
||||
WebpackLoadersOptions,
|
||||
},
|
||||
resolve_options_context::{ResolveOptionsContext, ResolveOptionsContextVc},
|
||||
transition::TransitionVc,
|
||||
resolve_options_context::ResolveOptionsContext,
|
||||
transition::Transition,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
use super::{
|
||||
resolve::ExternalCjsModulesResolvePluginVc,
|
||||
resolve::ExternalCjsModulesResolvePlugin,
|
||||
transforms::{get_next_server_internal_transforms_rules, get_next_server_transforms_rules},
|
||||
};
|
||||
use crate::{
|
||||
|
@ -45,12 +41,12 @@ use crate::{
|
|||
env::env_for_js,
|
||||
mode::NextMode,
|
||||
next_build::{get_external_next_compiled_package_mapping, get_postcss_package_mapping},
|
||||
next_client::{RuntimeEntriesVc, RuntimeEntry},
|
||||
next_config::NextConfigVc,
|
||||
next_client::{RuntimeEntries, RuntimeEntry},
|
||||
next_config::NextConfig,
|
||||
next_import_map::{get_next_server_import_map, mdx_import_source_file},
|
||||
next_server::resolve::ExternalPredicate,
|
||||
next_shared::{
|
||||
resolve::UnsupportedModulesResolvePluginVc,
|
||||
resolve::UnsupportedModulesResolvePlugin,
|
||||
transforms::{
|
||||
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
|
||||
styled_components::get_styled_components_transform_plugin,
|
||||
|
@ -70,46 +66,46 @@ use crate::{
|
|||
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord)]
|
||||
pub enum ServerContextType {
|
||||
Pages {
|
||||
pages_dir: FileSystemPathVc,
|
||||
pages_dir: Vc<FileSystemPath>,
|
||||
},
|
||||
PagesData {
|
||||
pages_dir: FileSystemPathVc,
|
||||
pages_dir: Vc<FileSystemPath>,
|
||||
},
|
||||
AppSSR {
|
||||
app_dir: FileSystemPathVc,
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
},
|
||||
AppRSC {
|
||||
app_dir: FileSystemPathVc,
|
||||
ecmascript_client_reference_transition_name: Option<StringVc>,
|
||||
client_transition: Option<TransitionVc>,
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
ecmascript_client_reference_transition_name: Option<Vc<String>>,
|
||||
client_transition: Option<Vc<Box<dyn Transition>>>,
|
||||
},
|
||||
AppRoute {
|
||||
app_dir: FileSystemPathVc,
|
||||
app_dir: Vc<FileSystemPath>,
|
||||
},
|
||||
Middleware,
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_server_resolve_options_context(
|
||||
project_path: FileSystemPathVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
ty: Value<ServerContextType>,
|
||||
mode: NextMode,
|
||||
next_config: NextConfigVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
) -> Result<ResolveOptionsContextVc> {
|
||||
next_config: Vc<NextConfig>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
) -> Result<Vc<ResolveOptionsContext>> {
|
||||
let next_server_import_map =
|
||||
get_next_server_import_map(project_path, ty, mode, next_config, execution_context);
|
||||
let foreign_code_context_condition = foreign_code_context_condition(next_config).await?;
|
||||
let root_dir = project_path.root().resolve().await?;
|
||||
let unsupported_modules_resolve_plugin = UnsupportedModulesResolvePluginVc::new(project_path);
|
||||
let server_component_externals_plugin = ExternalCjsModulesResolvePluginVc::new(
|
||||
let unsupported_modules_resolve_plugin = UnsupportedModulesResolvePlugin::new(project_path);
|
||||
let server_component_externals_plugin = ExternalCjsModulesResolvePlugin::new(
|
||||
project_path,
|
||||
ExternalPredicate::Only(next_config.server_component_externals()).cell(),
|
||||
);
|
||||
|
||||
Ok(match ty.into_value() {
|
||||
ServerContextType::Pages { .. } | ServerContextType::PagesData { .. } => {
|
||||
let external_cjs_modules_plugin = ExternalCjsModulesResolvePluginVc::new(
|
||||
let external_cjs_modules_plugin = ExternalCjsModulesResolvePlugin::new(
|
||||
project_path,
|
||||
ExternalPredicate::AllExcept(next_config.transpile_packages()).cell(),
|
||||
);
|
||||
|
@ -122,8 +118,8 @@ pub async fn get_server_resolve_options_context(
|
|||
custom_conditions: vec![mode.node_env().to_string(), "node".to_string()],
|
||||
import_map: Some(next_server_import_map),
|
||||
plugins: vec![
|
||||
external_cjs_modules_plugin.into(),
|
||||
unsupported_modules_resolve_plugin.into(),
|
||||
Vc::upcast(external_cjs_modules_plugin),
|
||||
Vc::upcast(unsupported_modules_resolve_plugin),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
@ -150,8 +146,8 @@ pub async fn get_server_resolve_options_context(
|
|||
],
|
||||
import_map: Some(next_server_import_map),
|
||||
plugins: vec![
|
||||
server_component_externals_plugin.into(),
|
||||
unsupported_modules_resolve_plugin.into(),
|
||||
Vc::upcast(server_component_externals_plugin),
|
||||
Vc::upcast(unsupported_modules_resolve_plugin),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
@ -179,8 +175,8 @@ pub async fn get_server_resolve_options_context(
|
|||
],
|
||||
import_map: Some(next_server_import_map),
|
||||
plugins: vec![
|
||||
server_component_externals_plugin.into(),
|
||||
unsupported_modules_resolve_plugin.into(),
|
||||
Vc::upcast(server_component_externals_plugin),
|
||||
Vc::upcast(unsupported_modules_resolve_plugin),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
@ -201,8 +197,8 @@ pub async fn get_server_resolve_options_context(
|
|||
custom_conditions: vec![mode.node_env().to_string(), "node".to_string()],
|
||||
import_map: Some(next_server_import_map),
|
||||
plugins: vec![
|
||||
server_component_externals_plugin.into(),
|
||||
unsupported_modules_resolve_plugin.into(),
|
||||
Vc::upcast(server_component_externals_plugin),
|
||||
Vc::upcast(unsupported_modules_resolve_plugin),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
@ -222,7 +218,7 @@ pub async fn get_server_resolve_options_context(
|
|||
enable_node_externals: true,
|
||||
module: true,
|
||||
custom_conditions: vec![mode.node_env().to_string()],
|
||||
plugins: vec![unsupported_modules_resolve_plugin.into()],
|
||||
plugins: vec![Vc::upcast(unsupported_modules_resolve_plugin)],
|
||||
..Default::default()
|
||||
};
|
||||
ResolveOptionsContext {
|
||||
|
@ -251,23 +247,23 @@ fn defines(mode: NextMode) -> CompileTimeDefines {
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn next_server_defines(mode: NextMode) -> CompileTimeDefinesVc {
|
||||
fn next_server_defines(mode: NextMode) -> Vc<CompileTimeDefines> {
|
||||
defines(mode).cell()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn next_server_free_vars(mode: NextMode) -> Result<FreeVarReferencesVc> {
|
||||
async fn next_server_free_vars(mode: NextMode) -> Result<Vc<FreeVarReferences>> {
|
||||
Ok(free_var_references!(..defines(mode).into_iter()).cell())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub fn get_server_compile_time_info(
|
||||
mode: NextMode,
|
||||
process_env: ProcessEnvVc,
|
||||
server_addr: ServerAddrVc,
|
||||
) -> CompileTimeInfoVc {
|
||||
CompileTimeInfo::builder(EnvironmentVc::new(Value::new(
|
||||
ExecutionEnvironment::NodeJsLambda(NodeJsEnvironmentVc::current(process_env, server_addr)),
|
||||
process_env: Vc<Box<dyn ProcessEnv>>,
|
||||
server_addr: Vc<ServerAddr>,
|
||||
) -> Vc<CompileTimeInfo> {
|
||||
CompileTimeInfo::builder(Environment::new(Value::new(
|
||||
ExecutionEnvironment::NodeJsLambda(NodeJsEnvironment::current(process_env, server_addr)),
|
||||
)))
|
||||
.defines(next_server_defines(mode))
|
||||
.free_var_references(next_server_free_vars(mode))
|
||||
|
@ -276,12 +272,12 @@ pub fn get_server_compile_time_info(
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn get_server_module_options_context(
|
||||
project_path: FileSystemPathVc,
|
||||
execution_context: ExecutionContextVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
execution_context: Vc<ExecutionContext>,
|
||||
ty: Value<ServerContextType>,
|
||||
mode: NextMode,
|
||||
next_config: NextConfigVc,
|
||||
) -> Result<ModuleOptionsContextVc> {
|
||||
next_config: Vc<NextConfig>,
|
||||
) -> Result<Vc<ModuleOptionsContext>> {
|
||||
let custom_rules = get_next_server_transforms_rules(next_config, ty.into_value(), mode).await?;
|
||||
let internal_custom_rules = get_next_server_internal_transforms_rules(ty.into_value()).await?;
|
||||
|
||||
|
@ -297,9 +293,9 @@ pub async fn get_server_module_options_context(
|
|||
let enable_webpack_loaders = webpack_rules.map(|rules| {
|
||||
WebpackLoadersOptions {
|
||||
rules,
|
||||
loader_runner_package: Some(get_external_next_compiled_package_mapping(
|
||||
StringVc::cell("loader-runner".to_owned()),
|
||||
)),
|
||||
loader_runner_package: Some(get_external_next_compiled_package_mapping(Vc::cell(
|
||||
"loader-runner".to_owned(),
|
||||
))),
|
||||
}
|
||||
.cell()
|
||||
});
|
||||
|
@ -308,13 +304,12 @@ pub async fn get_server_module_options_context(
|
|||
let styled_components_transform_plugin =
|
||||
*get_styled_components_transform_plugin(next_config).await?;
|
||||
let styled_jsx_transform_plugin = *get_styled_jsx_transform_plugin().await?;
|
||||
let server_directive_transform_plugin = Some(TransformPluginVc::cell(Box::new(
|
||||
ServerDirectiveTransformer::new(
|
||||
let server_directive_transform_plugin =
|
||||
Some(Vc::cell(Box::new(ServerDirectiveTransformer::new(
|
||||
// ServerDirective is not implemented yet and always reports an issue.
|
||||
// We don't have to pass a valid transition name yet, but the API is prepared.
|
||||
&StringVc::cell("TODO".to_string()),
|
||||
),
|
||||
)));
|
||||
&Vc::cell("TODO".to_string()),
|
||||
)) as _));
|
||||
|
||||
// ModuleOptionsContext related options
|
||||
let tsconfig = get_typescript_transform_options(project_path);
|
||||
|
@ -331,7 +326,7 @@ pub async fn get_server_module_options_context(
|
|||
};
|
||||
let jsx_runtime_options = get_jsx_transform_options(project_path, mode, None);
|
||||
|
||||
let source_transforms: Vec<TransformPluginVc> = vec![
|
||||
let source_transforms: Vec<Vc<TransformPlugin>> = vec![
|
||||
*get_swc_ecma_transform_plugin(project_path, next_config).await?,
|
||||
*get_relay_transform_plugin(next_config).await?,
|
||||
*get_emotion_transform_plugin(next_config).await?,
|
||||
|
@ -342,7 +337,7 @@ pub async fn get_server_module_options_context(
|
|||
|
||||
let output_transforms = vec![];
|
||||
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||
CustomEcmascriptTransformPlugins {
|
||||
source_transforms: source_transforms.clone(),
|
||||
output_transforms: output_transforms.clone(),
|
||||
|
@ -351,7 +346,7 @@ pub async fn get_server_module_options_context(
|
|||
|
||||
let module_options_context = match ty.into_value() {
|
||||
ServerContextType::Pages { .. } | ServerContextType::PagesData { .. } => {
|
||||
let mut base_source_transforms: Vec<TransformPluginVc> = vec![
|
||||
let mut base_source_transforms: Vec<Vc<TransformPlugin>> = vec![
|
||||
styled_components_transform_plugin,
|
||||
styled_jsx_transform_plugin,
|
||||
]
|
||||
|
@ -361,7 +356,7 @@ pub async fn get_server_module_options_context(
|
|||
|
||||
base_source_transforms.extend(source_transforms);
|
||||
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||
CustomEcmascriptTransformPlugins {
|
||||
source_transforms: base_source_transforms,
|
||||
output_transforms,
|
||||
|
@ -403,7 +398,7 @@ pub async fn get_server_module_options_context(
|
|||
}
|
||||
}
|
||||
ServerContextType::AppSSR { .. } => {
|
||||
let mut base_source_transforms: Vec<TransformPluginVc> = vec![
|
||||
let mut base_source_transforms: Vec<Vc<TransformPlugin>> = vec![
|
||||
styled_components_transform_plugin,
|
||||
styled_jsx_transform_plugin,
|
||||
server_directive_transform_plugin,
|
||||
|
@ -412,7 +407,7 @@ pub async fn get_server_module_options_context(
|
|||
.flatten()
|
||||
.collect();
|
||||
|
||||
let base_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
||||
let base_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||
CustomEcmascriptTransformPlugins {
|
||||
source_transforms: base_source_transforms.clone(),
|
||||
output_transforms: vec![],
|
||||
|
@ -421,7 +416,7 @@ pub async fn get_server_module_options_context(
|
|||
|
||||
base_source_transforms.extend(source_transforms);
|
||||
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||
CustomEcmascriptTransformPlugins {
|
||||
source_transforms: base_source_transforms,
|
||||
output_transforms,
|
||||
|
@ -465,7 +460,7 @@ pub async fn get_server_module_options_context(
|
|||
ecmascript_client_reference_transition_name,
|
||||
..
|
||||
} => {
|
||||
let mut base_source_transforms: Vec<TransformPluginVc> = vec![
|
||||
let mut base_source_transforms: Vec<Vc<TransformPlugin>> = vec![
|
||||
styled_components_transform_plugin,
|
||||
server_directive_transform_plugin,
|
||||
]
|
||||
|
@ -476,12 +471,12 @@ pub async fn get_server_module_options_context(
|
|||
if let Some(ecmascript_client_reference_transition_name) =
|
||||
ecmascript_client_reference_transition_name
|
||||
{
|
||||
base_source_transforms.push(TransformPluginVc::cell(Box::new(
|
||||
ClientDirectiveTransformer::new(ecmascript_client_reference_transition_name),
|
||||
)));
|
||||
base_source_transforms.push(Vc::cell(Box::new(ClientDirectiveTransformer::new(
|
||||
ecmascript_client_reference_transition_name,
|
||||
)) as _));
|
||||
}
|
||||
|
||||
let base_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
||||
let base_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||
CustomEcmascriptTransformPlugins {
|
||||
source_transforms: base_source_transforms.clone(),
|
||||
output_transforms: vec![],
|
||||
|
@ -490,7 +485,7 @@ pub async fn get_server_module_options_context(
|
|||
|
||||
base_source_transforms.extend(source_transforms);
|
||||
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||
CustomEcmascriptTransformPlugins {
|
||||
source_transforms: base_source_transforms,
|
||||
output_transforms,
|
||||
|
@ -561,7 +556,7 @@ pub async fn get_server_module_options_context(
|
|||
}
|
||||
}
|
||||
ServerContextType::Middleware => {
|
||||
let mut base_source_transforms: Vec<TransformPluginVc> = vec![
|
||||
let mut base_source_transforms: Vec<Vc<TransformPlugin>> = vec![
|
||||
styled_components_transform_plugin,
|
||||
styled_jsx_transform_plugin,
|
||||
]
|
||||
|
@ -571,7 +566,7 @@ pub async fn get_server_module_options_context(
|
|||
|
||||
base_source_transforms.extend(source_transforms);
|
||||
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||
CustomEcmascriptTransformPlugins {
|
||||
source_transforms: base_source_transforms,
|
||||
output_transforms,
|
||||
|
@ -616,7 +611,7 @@ pub async fn get_server_module_options_context(
|
|||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub fn get_build_module_options_context() -> ModuleOptionsContextVc {
|
||||
pub fn get_build_module_options_context() -> Vc<ModuleOptionsContext> {
|
||||
ModuleOptionsContext {
|
||||
enable_typescript_transform: Some(Default::default()),
|
||||
..Default::default()
|
||||
|
@ -626,15 +621,16 @@ pub fn get_build_module_options_context() -> ModuleOptionsContextVc {
|
|||
|
||||
#[turbo_tasks::function]
|
||||
pub fn get_server_runtime_entries(
|
||||
project_root: FileSystemPathVc,
|
||||
env: ProcessEnvVc,
|
||||
project_root: Vc<FileSystemPath>,
|
||||
env: Vc<Box<dyn ProcessEnv>>,
|
||||
ty: Value<ServerContextType>,
|
||||
mode: NextMode,
|
||||
next_config: NextConfigVc,
|
||||
) -> RuntimeEntriesVc {
|
||||
let mut runtime_entries = vec![RuntimeEntry::Source(
|
||||
ProcessEnvAssetVc::new(project_root, env_for_js(env, false, next_config)).into(),
|
||||
)
|
||||
next_config: Vc<NextConfig>,
|
||||
) -> Vc<RuntimeEntries> {
|
||||
let mut runtime_entries = vec![RuntimeEntry::Source(Vc::upcast(ProcessEnvAsset::new(
|
||||
project_root,
|
||||
env_for_js(env, false, next_config),
|
||||
)))
|
||||
.cell()];
|
||||
|
||||
match mode {
|
||||
|
@ -643,10 +639,10 @@ pub fn get_server_runtime_entries(
|
|||
if let ServerContextType::AppRSC { .. } = ty.into_value() {
|
||||
runtime_entries.push(
|
||||
RuntimeEntry::Request(
|
||||
RequestVc::parse(Value::new(Pattern::Constant(
|
||||
Request::parse(Value::new(Pattern::Constant(
|
||||
"./build/server/app-bootstrap.ts".to_string(),
|
||||
))),
|
||||
next_js_fs().root().join("_"),
|
||||
next_js_fs().root().join("_".to_string()),
|
||||
)
|
||||
.cell(),
|
||||
);
|
||||
|
@ -654,26 +650,26 @@ pub fn get_server_runtime_entries(
|
|||
}
|
||||
}
|
||||
|
||||
RuntimeEntriesVc::cell(runtime_entries)
|
||||
Vc::cell(runtime_entries)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub fn get_server_chunking_context(
|
||||
project_path: FileSystemPathVc,
|
||||
node_root: FileSystemPathVc,
|
||||
project_path: Vc<FileSystemPath>,
|
||||
node_root: Vc<FileSystemPath>,
|
||||
// TODO(alexkirsz) Is this even necessary? Are assets not always on the client chunking context
|
||||
// anyway?
|
||||
client_root: FileSystemPathVc,
|
||||
environment: EnvironmentVc,
|
||||
) -> BuildChunkingContextVc {
|
||||
client_root: Vc<FileSystemPath>,
|
||||
environment: Vc<Environment>,
|
||||
) -> Vc<BuildChunkingContext> {
|
||||
// TODO(alexkirsz) This should return a trait that can be implemented by the
|
||||
// different server chunking contexts. OR the build chunking context should
|
||||
// support both production and development modes.
|
||||
BuildChunkingContextVc::builder(
|
||||
BuildChunkingContext::builder(
|
||||
project_path,
|
||||
node_root,
|
||||
node_root.join("server/chunks"),
|
||||
client_root.join("static/media"),
|
||||
node_root.join("server/chunks".to_string()),
|
||||
client_root.join("static/media".to_string()),
|
||||
environment,
|
||||
)
|
||||
.build()
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
use anyhow::Result;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use turbo_tasks::primitives::{BoolVc, StringsVc};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::{glob::GlobVc, FileJsonContent, FileSystemPathVc},
|
||||
turbo::tasks_fs::{glob::Glob, FileJsonContent, FileSystemPath},
|
||||
turbopack::core::{
|
||||
asset::Asset,
|
||||
resolve::{
|
||||
find_context_file,
|
||||
node::node_cjs_resolve_options,
|
||||
package_json,
|
||||
parse::{Request, RequestVc},
|
||||
plugin::{ResolvePlugin, ResolvePluginConditionVc, ResolvePluginVc},
|
||||
parse::Request,
|
||||
plugin::{ResolvePlugin, ResolvePluginCondition},
|
||||
resolve, FindContextFileResult, PrimaryResolveResult, ResolveResult,
|
||||
ResolveResultOptionVc,
|
||||
ResolveResultOption,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -23,9 +23,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(StringsVc),
|
||||
AllExcept(Vc<Vec<String>>),
|
||||
/// Only mark modules listed as external.
|
||||
Only(StringsVc),
|
||||
Only(Vc<Vec<String>>),
|
||||
}
|
||||
|
||||
/// Mark modules as external, so they're resolved at runtime instead of bundled.
|
||||
|
@ -34,65 +34,65 @@ pub enum ExternalPredicate {
|
|||
/// possible to resolve them at runtime.
|
||||
#[turbo_tasks::value]
|
||||
pub(crate) struct ExternalCjsModulesResolvePlugin {
|
||||
root: FileSystemPathVc,
|
||||
predicate: ExternalPredicateVc,
|
||||
root: Vc<FileSystemPath>,
|
||||
predicate: Vc<ExternalPredicate>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ExternalCjsModulesResolvePluginVc {
|
||||
impl ExternalCjsModulesResolvePlugin {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(root: FileSystemPathVc, predicate: ExternalPredicateVc) -> Self {
|
||||
pub fn new(root: Vc<FileSystemPath>, predicate: Vc<ExternalPredicate>) -> Vc<Self> {
|
||||
ExternalCjsModulesResolvePlugin { root, predicate }.cell()
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn is_node_resolveable(
|
||||
context: FileSystemPathVc,
|
||||
request: RequestVc,
|
||||
expected: FileSystemPathVc,
|
||||
) -> Result<BoolVc> {
|
||||
context: Vc<FileSystemPath>,
|
||||
request: Vc<Request>,
|
||||
expected: Vc<FileSystemPath>,
|
||||
) -> Result<Vc<bool>> {
|
||||
let node_resolve_result = resolve(context, request, node_cjs_resolve_options(context.root()));
|
||||
let primary_node_assets = node_resolve_result.primary_assets().await?;
|
||||
let Some(node_asset) = primary_node_assets.first() else {
|
||||
// can't resolve request with node.js options
|
||||
return Ok(BoolVc::cell(false));
|
||||
return Ok(Vc::cell(false));
|
||||
};
|
||||
|
||||
if node_asset.ident().path().resolve().await? != expected.resolve().await? {
|
||||
// node.js resolves to a different file
|
||||
return Ok(BoolVc::cell(false));
|
||||
return Ok(Vc::cell(false));
|
||||
}
|
||||
|
||||
Ok(BoolVc::cell(true))
|
||||
Ok(Vc::cell(true))
|
||||
}
|
||||
|
||||
static PNPM: Lazy<Regex> = Lazy::new(|| Regex::new(r"(?:/|^)node_modules/(.pnpm/.+)").unwrap());
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn condition(root: FileSystemPathVc) -> ResolvePluginConditionVc {
|
||||
ResolvePluginConditionVc::new(root.root(), GlobVc::new("**/node_modules/**"))
|
||||
fn condition(root: Vc<FileSystemPath>) -> Vc<ResolvePluginCondition> {
|
||||
ResolvePluginCondition::new(root.root(), Glob::new("**/node_modules/**".to_string()))
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
|
||||
#[turbo_tasks::function]
|
||||
fn after_resolve_condition(&self) -> ResolvePluginConditionVc {
|
||||
fn after_resolve_condition(&self) -> Vc<ResolvePluginCondition> {
|
||||
condition(self.root)
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn after_resolve(
|
||||
&self,
|
||||
fs_path: FileSystemPathVc,
|
||||
context: FileSystemPathVc,
|
||||
request: RequestVc,
|
||||
) -> Result<ResolveResultOptionVc> {
|
||||
fs_path: Vc<FileSystemPath>,
|
||||
context: Vc<FileSystemPath>,
|
||||
request: Vc<Request>,
|
||||
) -> Result<Vc<ResolveResultOption>> {
|
||||
if *condition(self.root).matches(context).await? {
|
||||
return Ok(ResolveResultOptionVc::none());
|
||||
return Ok(ResolveResultOption::none());
|
||||
}
|
||||
if !matches!(&*request.await?, Request::Module { .. }) {
|
||||
return Ok(ResolveResultOptionVc::none());
|
||||
return Ok(ResolveResultOption::none());
|
||||
}
|
||||
|
||||
let raw_fs_path = &*fs_path.await?;
|
||||
|
@ -103,14 +103,14 @@ impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
|
|||
let exception_glob = packages_glob(*exceptions).await?;
|
||||
|
||||
if exception_glob.execute(&raw_fs_path.path) {
|
||||
return Ok(ResolveResultOptionVc::none());
|
||||
return Ok(ResolveResultOption::none());
|
||||
}
|
||||
}
|
||||
ExternalPredicate::Only(externals) => {
|
||||
let external_glob = packages_glob(*externals).await?;
|
||||
|
||||
if !external_glob.execute(&raw_fs_path.path) {
|
||||
return Ok(ResolveResultOptionVc::none());
|
||||
return Ok(ResolveResultOption::none());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,33 +118,33 @@ impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
|
|||
// node.js only supports these file extensions
|
||||
// mjs is an esm module and we can't bundle that yet
|
||||
if !matches!(
|
||||
raw_fs_path.extension(),
|
||||
raw_fs_path.extension_ref(),
|
||||
Some("cjs" | "js" | "node" | "json")
|
||||
) {
|
||||
return Ok(ResolveResultOptionVc::none());
|
||||
return Ok(ResolveResultOption::none());
|
||||
}
|
||||
|
||||
let FindContextFileResult::Found(package_json, _) =
|
||||
*find_context_file(fs_path.parent(), package_json()).await?
|
||||
else {
|
||||
// can't find package.json
|
||||
return Ok(ResolveResultOptionVc::none());
|
||||
return Ok(ResolveResultOption::none());
|
||||
};
|
||||
let FileJsonContent::Content(package) = &*package_json.read_json().await? else {
|
||||
// can't parse package.json
|
||||
return Ok(ResolveResultOptionVc::none());
|
||||
return Ok(ResolveResultOption::none());
|
||||
};
|
||||
|
||||
// always bundle esm modules
|
||||
if let Some("module") = package["type"].as_str() {
|
||||
return Ok(ResolveResultOptionVc::none());
|
||||
return Ok(ResolveResultOption::none());
|
||||
}
|
||||
|
||||
// check if we can resolve the package from the project dir with node.js resolve
|
||||
// options (might be hidden by pnpm)
|
||||
if *is_node_resolveable(self.root.root(), request, fs_path).await? {
|
||||
// mark as external
|
||||
return Ok(ResolveResultOptionVc::some(
|
||||
return Ok(ResolveResultOption::some(
|
||||
ResolveResult::primary(PrimaryResolveResult::OriginalReferenceExternal).cell(),
|
||||
));
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
|
|||
// options, to come here like the `module` field in package.json
|
||||
if *is_node_resolveable(context, request, fs_path).await? {
|
||||
// mark as external
|
||||
return Ok(ResolveResultOptionVc::some(
|
||||
return Ok(ResolveResultOption::some(
|
||||
ResolveResult::primary(
|
||||
PrimaryResolveResult::OriginalReferenceTypeExternal(
|
||||
import_path.as_str().to_string(),
|
||||
|
@ -172,13 +172,13 @@ impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
|
|||
}
|
||||
}
|
||||
}
|
||||
Ok(ResolveResultOptionVc::none())
|
||||
Ok(ResolveResultOption::none())
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn packages_glob(packages: StringsVc) -> Result<GlobVc> {
|
||||
Ok(GlobVc::new(&format!(
|
||||
async fn packages_glob(packages: Vc<Vec<String>>) -> Result<Vc<Glob>> {
|
||||
Ok(Glob::new(format!(
|
||||
"**/node_modules/{{{}}}/**",
|
||||
packages.await?.join(",")
|
||||
)))
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use anyhow::Result;
|
||||
use next_transform_strip_page_exports::ExportFilter;
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::turbopack::module_options::ModuleRule;
|
||||
|
||||
use crate::{
|
||||
mode::NextMode,
|
||||
next_client_reference::css_client_reference::css_client_reference_rule::get_next_css_client_reference_transforms_rule,
|
||||
next_config::NextConfigVc,
|
||||
next_config::NextConfig,
|
||||
next_server::context::ServerContextType,
|
||||
next_shared::transforms::{
|
||||
get_next_dynamic_transform_rule, get_next_font_transform_rule, get_next_image_rule,
|
||||
|
@ -16,7 +17,7 @@ use crate::{
|
|||
/// Returns a list of module rules which apply server-side, Next.js-specific
|
||||
/// transforms.
|
||||
pub async fn get_next_server_transforms_rules(
|
||||
next_config: NextConfigVc,
|
||||
next_config: Vc<NextConfig>,
|
||||
context_ty: ServerContextType,
|
||||
mode: NextMode,
|
||||
) -> Result<Vec<ModuleRule>> {
|
||||
|
|
|
@ -2,4 +2,4 @@ pub(crate) mod server_component_module;
|
|||
pub(crate) mod server_component_reference;
|
||||
pub(crate) mod server_component_transition;
|
||||
|
||||
pub use server_component_transition::NextServerComponentTransitionVc;
|
||||
pub use server_component_transition::NextServerComponentTransition;
|
||||
|
|
|
@ -1,50 +1,49 @@
|
|||
use anyhow::{bail, Result};
|
||||
use indoc::formatdoc;
|
||||
use turbo_tasks::{primitives::StringVc, Value};
|
||||
use turbo_tasks_fs::FileSystemPathVc;
|
||||
use turbo_tasks::{Value, Vc};
|
||||
use turbo_tasks_fs::FileSystemPath;
|
||||
use turbopack_binding::turbopack::{
|
||||
core::{
|
||||
asset::{Asset, AssetContentVc, AssetVc},
|
||||
asset::{Asset, AssetContent},
|
||||
chunk::{
|
||||
availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableModule,
|
||||
ChunkableModuleVc, ChunkingContextVc,
|
||||
availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableModule, ChunkingContext,
|
||||
},
|
||||
ident::AssetIdentVc,
|
||||
module::{Module, ModuleVc},
|
||||
reference::{AssetReferenceVc, AssetReferencesVc},
|
||||
ident::AssetIdent,
|
||||
module::Module,
|
||||
reference::{AssetReference, AssetReferences},
|
||||
},
|
||||
ecmascript::chunk::EcmascriptChunkItemExt,
|
||||
turbopack::ecmascript::{
|
||||
chunk::{
|
||||
EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc,
|
||||
EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc,
|
||||
EcmascriptChunkVc, EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc,
|
||||
EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkItemContent,
|
||||
EcmascriptChunkPlaceable, EcmascriptChunkingContext, EcmascriptExports,
|
||||
},
|
||||
utils::StringifyJs,
|
||||
},
|
||||
};
|
||||
|
||||
use super::server_component_reference::NextServerComponentModuleReferenceVc;
|
||||
use super::server_component_reference::NextServerComponentModuleReference;
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn modifier() -> StringVc {
|
||||
StringVc::cell("Next.js server component".to_string())
|
||||
fn modifier() -> Vc<String> {
|
||||
Vc::cell("Next.js server component".to_string())
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct NextServerComponentModule {
|
||||
module: EcmascriptChunkPlaceableVc,
|
||||
module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextServerComponentModuleVc {
|
||||
impl NextServerComponentModule {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(module: EcmascriptChunkPlaceableVc) -> Self {
|
||||
pub fn new(module: Vc<Box<dyn EcmascriptChunkPlaceable>>) -> Vc<Self> {
|
||||
NextServerComponentModule { module }.cell()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
pub async fn server_path(self_vc: NextServerComponentModuleVc) -> Result<FileSystemPathVc> {
|
||||
let this = self_vc.await?;
|
||||
pub async fn server_path(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
|
||||
let this = self.await?;
|
||||
Ok(this.module.ident().path())
|
||||
}
|
||||
}
|
||||
|
@ -52,20 +51,21 @@ impl NextServerComponentModuleVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl Asset for NextServerComponentModule {
|
||||
#[turbo_tasks::function]
|
||||
fn ident(&self) -> AssetIdentVc {
|
||||
fn ident(&self) -> Vc<AssetIdent> {
|
||||
self.module.ident().with_modifier(modifier())
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn content(&self) -> Result<AssetContentVc> {
|
||||
fn content(&self) -> Result<Vc<AssetContent>> {
|
||||
bail!("Next.js server component module has no content")
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn references(&self) -> AssetReferencesVc {
|
||||
let references: Vec<AssetReferenceVc> =
|
||||
vec![NextServerComponentModuleReferenceVc::new(self.module.into()).into()];
|
||||
AssetReferencesVc::cell(references)
|
||||
fn references(&self) -> Vc<AssetReferences> {
|
||||
let references: Vec<Vc<Box<dyn AssetReference>>> = vec![Vc::upcast(
|
||||
NextServerComponentModuleReference::new(Vc::upcast(self.module)),
|
||||
)];
|
||||
Vc::cell(references)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,16 +76,15 @@ impl Module for NextServerComponentModule {}
|
|||
impl ChunkableModule for NextServerComponentModule {
|
||||
#[turbo_tasks::function]
|
||||
fn as_chunk(
|
||||
self_vc: NextServerComponentModuleVc,
|
||||
context: ChunkingContextVc,
|
||||
self: Vc<Self>,
|
||||
context: Vc<Box<dyn ChunkingContext>>,
|
||||
availability_info: Value<AvailabilityInfo>,
|
||||
) -> ChunkVc {
|
||||
EcmascriptChunkVc::new(
|
||||
) -> Vc<Box<dyn Chunk>> {
|
||||
Vc::upcast(EcmascriptChunk::new(
|
||||
context,
|
||||
self_vc.as_ecmascript_chunk_placeable(),
|
||||
Vc::upcast(self),
|
||||
availability_info,
|
||||
)
|
||||
.into()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,19 +92,20 @@ impl ChunkableModule for NextServerComponentModule {
|
|||
impl EcmascriptChunkPlaceable for NextServerComponentModule {
|
||||
#[turbo_tasks::function]
|
||||
async fn as_chunk_item(
|
||||
self_vc: NextServerComponentModuleVc,
|
||||
context: EcmascriptChunkingContextVc,
|
||||
) -> Result<EcmascriptChunkItemVc> {
|
||||
Ok(BuildServerComponentChunkItem {
|
||||
context,
|
||||
inner: self_vc,
|
||||
}
|
||||
.cell()
|
||||
.into())
|
||||
self: Vc<Self>,
|
||||
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
) -> Result<Vc<Box<dyn EcmascriptChunkItem>>> {
|
||||
Ok(Vc::upcast(
|
||||
BuildServerComponentChunkItem {
|
||||
context,
|
||||
inner: self,
|
||||
}
|
||||
.cell(),
|
||||
))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn get_exports(&self) -> EcmascriptExportsVc {
|
||||
fn get_exports(&self) -> Vc<EcmascriptExports> {
|
||||
// TODO This should be EsmExports
|
||||
EcmascriptExports::Value.cell()
|
||||
}
|
||||
|
@ -113,22 +113,20 @@ impl EcmascriptChunkPlaceable for NextServerComponentModule {
|
|||
|
||||
#[turbo_tasks::value]
|
||||
struct BuildServerComponentChunkItem {
|
||||
context: EcmascriptChunkingContextVc,
|
||||
inner: NextServerComponentModuleVc,
|
||||
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||
inner: Vc<NextServerComponentModule>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl EcmascriptChunkItem for BuildServerComponentChunkItem {
|
||||
#[turbo_tasks::function]
|
||||
fn chunking_context(&self) -> EcmascriptChunkingContextVc {
|
||||
fn chunking_context(&self) -> Vc<Box<dyn EcmascriptChunkingContext>> {
|
||||
self.context
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn content(
|
||||
self_vc: BuildServerComponentChunkItemVc,
|
||||
) -> Result<EcmascriptChunkItemContentVc> {
|
||||
let this = self_vc.await?;
|
||||
async fn content(self: Vc<Self>) -> Result<Vc<EcmascriptChunkItemContent>> {
|
||||
let this = self.await?;
|
||||
let inner = this.inner.await?;
|
||||
|
||||
let module_id = inner.module.as_chunk_item(this.context).id().await?;
|
||||
|
@ -151,12 +149,12 @@ impl EcmascriptChunkItem for BuildServerComponentChunkItem {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ChunkItem for BuildServerComponentChunkItem {
|
||||
#[turbo_tasks::function]
|
||||
fn asset_ident(&self) -> AssetIdentVc {
|
||||
fn asset_ident(&self) -> Vc<AssetIdent> {
|
||||
self.inner.ident()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn references(&self) -> AssetReferencesVc {
|
||||
fn references(&self) -> Vc<AssetReferences> {
|
||||
self.inner.references()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,21 @@
|
|||
use anyhow::Result;
|
||||
use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc};
|
||||
use turbo_tasks::{ValueToString, Vc};
|
||||
use turbopack_binding::turbopack::core::{
|
||||
asset::{Asset, AssetVc},
|
||||
chunk::{
|
||||
ChunkableModuleReference, ChunkableModuleReferenceVc, ChunkingType, ChunkingTypeOptionVc,
|
||||
},
|
||||
reference::{AssetReference, AssetReferenceVc},
|
||||
resolve::{ResolveResult, ResolveResultVc},
|
||||
asset::Asset,
|
||||
chunk::{ChunkableModuleReference, ChunkingType, ChunkingTypeOption},
|
||||
reference::AssetReference,
|
||||
resolve::ResolveResult,
|
||||
};
|
||||
|
||||
#[turbo_tasks::value]
|
||||
pub struct NextServerComponentModuleReference {
|
||||
asset: AssetVc,
|
||||
asset: Vc<Box<dyn Asset>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextServerComponentModuleReferenceVc {
|
||||
impl NextServerComponentModuleReference {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(asset: AssetVc) -> Self {
|
||||
pub fn new(asset: Vc<Box<dyn Asset>>) -> Vc<Self> {
|
||||
NextServerComponentModuleReference { asset }.cell()
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +23,8 @@ impl NextServerComponentModuleReferenceVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ValueToString for NextServerComponentModuleReference {
|
||||
#[turbo_tasks::function]
|
||||
async fn to_string(&self) -> Result<StringVc> {
|
||||
Ok(StringVc::cell(format!(
|
||||
async fn to_string(&self) -> Result<Vc<String>> {
|
||||
Ok(Vc::cell(format!(
|
||||
"Next.js server component {}",
|
||||
self.asset.ident().to_string().await?
|
||||
)))
|
||||
|
@ -36,7 +34,7 @@ impl ValueToString for NextServerComponentModuleReference {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl AssetReference for NextServerComponentModuleReference {
|
||||
#[turbo_tasks::function]
|
||||
fn resolve_reference(&self) -> ResolveResultVc {
|
||||
fn resolve_reference(&self) -> Vc<ResolveResult> {
|
||||
ResolveResult::asset(self.asset).cell()
|
||||
}
|
||||
}
|
||||
|
@ -44,9 +42,9 @@ impl AssetReference for NextServerComponentModuleReference {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ChunkableModuleReference for NextServerComponentModuleReference {
|
||||
#[turbo_tasks::function]
|
||||
fn chunking_type(&self) -> ChunkingTypeOptionVc {
|
||||
fn chunking_type(&self) -> Vc<ChunkingTypeOption> {
|
||||
// TODO(alexkirsz) Instead of isolated parallel, have the server component
|
||||
// reference create a new chunk group entirely?
|
||||
ChunkingTypeOptionVc::cell(Some(ChunkingType::IsolatedParallel))
|
||||
Vc::cell(Some(ChunkingType::IsolatedParallel))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
use anyhow::{bail, Result};
|
||||
use turbo_tasks::Vc;
|
||||
use turbopack_binding::turbopack::{
|
||||
core::module::ModuleVc,
|
||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
||||
turbopack::{
|
||||
transition::{Transition, TransitionVc},
|
||||
ModuleAssetContextVc,
|
||||
},
|
||||
core::module::Module,
|
||||
ecmascript::chunk::EcmascriptChunkPlaceable,
|
||||
turbopack::{transition::Transition, ModuleAssetContext},
|
||||
};
|
||||
|
||||
use super::server_component_module::NextServerComponentModuleVc;
|
||||
use super::server_component_module::NextServerComponentModule;
|
||||
|
||||
/// This transition wraps a module into a marker
|
||||
/// [`NextServerComponentModuleVc`].
|
||||
/// [`Vc<NextServerComponentModule>`].
|
||||
///
|
||||
/// When walking the module graph to build the client reference manifest, this
|
||||
/// is used to determine under which server component CSS client references are
|
||||
|
@ -20,10 +18,10 @@ use super::server_component_module::NextServerComponentModuleVc;
|
|||
pub struct NextServerComponentTransition {}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl NextServerComponentTransitionVc {
|
||||
/// Creates a new [`NextServerComponentTransitionVc`].
|
||||
impl NextServerComponentTransition {
|
||||
/// Creates a new [`Vc<NextServerComponentTransition>`].
|
||||
#[turbo_tasks::function]
|
||||
pub fn new() -> Self {
|
||||
pub fn new() -> Vc<Self> {
|
||||
NextServerComponentTransition {}.cell()
|
||||
}
|
||||
}
|
||||
|
@ -32,14 +30,16 @@ impl NextServerComponentTransitionVc {
|
|||
impl Transition for NextServerComponentTransition {
|
||||
#[turbo_tasks::function]
|
||||
async fn process_module(
|
||||
_self_vc: NextServerComponentTransitionVc,
|
||||
module: ModuleVc,
|
||||
_context: ModuleAssetContextVc,
|
||||
) -> Result<ModuleVc> {
|
||||
let Some(module) = EcmascriptChunkPlaceableVc::resolve_from(module).await? else {
|
||||
self: Vc<Self>,
|
||||
module: Vc<Box<dyn Module>>,
|
||||
_context: Vc<ModuleAssetContext>,
|
||||
) -> Result<Vc<Box<dyn Module>>> {
|
||||
let Some(module) =
|
||||
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(module).await?
|
||||
else {
|
||||
bail!("not an ecmascript module");
|
||||
};
|
||||
|
||||
Ok(NextServerComponentModuleVc::new(module).into())
|
||||
Ok(Vc::upcast(NextServerComponentModule::new(module)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,16 +2,17 @@ use std::collections::HashSet;
|
|||
|
||||
use anyhow::Result;
|
||||
use lazy_static::lazy_static;
|
||||
use turbo_tasks_fs::glob::GlobVc;
|
||||
use turbo_tasks::Vc;
|
||||
use turbo_tasks_fs::glob::Glob;
|
||||
use turbopack_binding::{
|
||||
turbo::tasks_fs::FileSystemPathVc,
|
||||
turbo::tasks_fs::FileSystemPath,
|
||||
turbopack::core::{
|
||||
issue::unsupported_module::UnsupportedModuleIssue,
|
||||
issue::{unsupported_module::UnsupportedModuleIssue, IssueExt},
|
||||
resolve::{
|
||||
parse::{Request, RequestVc},
|
||||
parse::Request,
|
||||
pattern::Pattern,
|
||||
plugin::{ResolvePlugin, ResolvePluginConditionVc, ResolvePluginVc},
|
||||
ResolveResultOptionVc,
|
||||
plugin::{ResolvePlugin, ResolvePluginCondition},
|
||||
ResolveResultOption,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -23,13 +24,13 @@ lazy_static! {
|
|||
|
||||
#[turbo_tasks::value]
|
||||
pub(crate) struct UnsupportedModulesResolvePlugin {
|
||||
root: FileSystemPathVc,
|
||||
root: Vc<FileSystemPath>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl UnsupportedModulesResolvePluginVc {
|
||||
impl UnsupportedModulesResolvePlugin {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(root: FileSystemPathVc) -> Self {
|
||||
pub fn new(root: Vc<FileSystemPath>) -> Vc<Self> {
|
||||
UnsupportedModulesResolvePlugin { root }.cell()
|
||||
}
|
||||
}
|
||||
|
@ -37,17 +38,17 @@ impl UnsupportedModulesResolvePluginVc {
|
|||
#[turbo_tasks::value_impl]
|
||||
impl ResolvePlugin for UnsupportedModulesResolvePlugin {
|
||||
#[turbo_tasks::function]
|
||||
fn after_resolve_condition(&self) -> ResolvePluginConditionVc {
|
||||
ResolvePluginConditionVc::new(self.root.root(), GlobVc::new("**"))
|
||||
fn after_resolve_condition(&self) -> Vc<ResolvePluginCondition> {
|
||||
ResolvePluginCondition::new(self.root.root(), Glob::new("**".to_string()))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn after_resolve(
|
||||
&self,
|
||||
_fs_path: FileSystemPathVc,
|
||||
context: FileSystemPathVc,
|
||||
request: RequestVc,
|
||||
) -> Result<ResolveResultOptionVc> {
|
||||
_fs_path: Vc<FileSystemPath>,
|
||||
context: Vc<FileSystemPath>,
|
||||
request: Vc<Request>,
|
||||
) -> Result<Vc<ResolveResultOption>> {
|
||||
if let Request::Module {
|
||||
module,
|
||||
path,
|
||||
|
@ -62,7 +63,6 @@ impl ResolvePlugin for UnsupportedModulesResolvePlugin {
|
|||
package_path: None,
|
||||
}
|
||||
.cell()
|
||||
.as_issue()
|
||||
.emit();
|
||||
}
|
||||
|
||||
|
@ -74,12 +74,11 @@ impl ResolvePlugin for UnsupportedModulesResolvePlugin {
|
|||
package_path: Some(path.to_owned()),
|
||||
}
|
||||
.cell()
|
||||
.as_issue()
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ResolveResultOptionVc::none())
|
||||
Ok(ResolveResultOption::none())
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue