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]]
|
[[package]]
|
||||||
name = "auto-hash-map"
|
name = "auto-hash-map"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -3599,7 +3599,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "node-file-trace"
|
name = "node-file-trace"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -7259,9 +7259,10 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks"
|
name = "turbo-tasks"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"async-trait",
|
||||||
"auto-hash-map",
|
"auto-hash-map",
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
|
@ -7290,7 +7291,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-build"
|
name = "turbo-tasks-build"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cargo-lock",
|
"cargo-lock",
|
||||||
|
@ -7302,7 +7303,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-bytes"
|
name = "turbo-tasks-bytes"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -7317,7 +7318,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-env"
|
name = "turbo-tasks-env"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"dotenvs",
|
"dotenvs",
|
||||||
|
@ -7331,7 +7332,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-fetch"
|
name = "turbo-tasks-fetch"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
@ -7348,7 +7349,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-fs"
|
name = "turbo-tasks-fs"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"auto-hash-map",
|
"auto-hash-map",
|
||||||
|
@ -7378,7 +7379,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-hash"
|
name = "turbo-tasks-hash"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"base16",
|
"base16",
|
||||||
"hex",
|
"hex",
|
||||||
|
@ -7390,7 +7391,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-macros"
|
name = "turbo-tasks-macros"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"convert_case 0.6.0",
|
"convert_case 0.6.0",
|
||||||
|
@ -7404,7 +7405,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-macros-shared"
|
name = "turbo-tasks-macros-shared"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -7414,7 +7415,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-malloc"
|
name = "turbo-tasks-malloc"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"mimalloc",
|
"mimalloc",
|
||||||
]
|
]
|
||||||
|
@ -7422,7 +7423,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-memory"
|
name = "turbo-tasks-memory"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"auto-hash-map",
|
"auto-hash-map",
|
||||||
|
@ -7445,7 +7446,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-testing"
|
name = "turbo-tasks-testing"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"auto-hash-map",
|
"auto-hash-map",
|
||||||
|
@ -7458,7 +7459,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack"
|
name = "turbopack"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
|
@ -7488,7 +7489,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-bench"
|
name = "turbopack-bench"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chromiumoxide",
|
"chromiumoxide",
|
||||||
|
@ -7518,7 +7519,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-binding"
|
name = "turbopack-binding"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"auto-hash-map",
|
"auto-hash-map",
|
||||||
"mdxjs",
|
"mdxjs",
|
||||||
|
@ -7560,7 +7561,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-build"
|
name = "turbopack-build"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
@ -7580,7 +7581,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-cli-utils"
|
name = "turbopack-cli-utils"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap 4.1.11",
|
"clap 4.1.11",
|
||||||
|
@ -7604,7 +7605,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-core"
|
name = "turbopack-core"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -7632,7 +7633,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-create-test-app"
|
name = "turbopack-create-test-app"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap 4.1.11",
|
"clap 4.1.11",
|
||||||
|
@ -7645,7 +7646,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-css"
|
name = "turbopack-css"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -7667,7 +7668,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-dev"
|
name = "turbopack-dev"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
@ -7691,7 +7692,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-dev-server"
|
name = "turbopack-dev-server"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
|
@ -7727,7 +7728,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-ecmascript"
|
name = "turbopack-ecmascript"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -7760,7 +7761,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-ecmascript-plugins"
|
name = "turbopack-ecmascript-plugins"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -7783,7 +7784,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-ecmascript-runtime"
|
name = "turbopack-ecmascript-runtime"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"indoc",
|
"indoc",
|
||||||
|
@ -7800,7 +7801,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-env"
|
name = "turbopack-env"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
@ -7816,7 +7817,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-image"
|
name = "turbopack-image"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.21.0",
|
"base64 0.21.0",
|
||||||
|
@ -7836,7 +7837,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-json"
|
name = "turbopack-json"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -7851,7 +7852,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-mdx"
|
name = "turbopack-mdx"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"mdxjs",
|
"mdxjs",
|
||||||
|
@ -7866,7 +7867,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-node"
|
name = "turbopack-node"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
|
@ -7901,7 +7902,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-static"
|
name = "turbopack-static"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -7917,7 +7918,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-swc-utils"
|
name = "turbopack-swc-utils"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"swc_core",
|
"swc_core",
|
||||||
"turbo-tasks",
|
"turbo-tasks",
|
||||||
|
@ -7928,7 +7929,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-test-utils"
|
name = "turbopack-test-utils"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
|
@ -44,11 +44,11 @@ swc_core = { version = "0.79.13" }
|
||||||
testing = { version = "0.33.20" }
|
testing = { version = "0.33.20" }
|
||||||
|
|
||||||
# Turbo crates
|
# 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..
|
# [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
|
# [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
|
# General Deps
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,9 @@ use next_swc::{
|
||||||
next_dynamic::next_dynamic,
|
next_dynamic::next_dynamic,
|
||||||
next_ssg::next_ssg,
|
next_ssg::next_ssg,
|
||||||
react_server_components::server_components,
|
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 next_transform_font::{next_font_loaders, Config as FontLoaderConfig};
|
||||||
use turbopack_binding::swc::{
|
use turbopack_binding::swc::{
|
||||||
|
|
|
@ -9,7 +9,9 @@ use next_swc::{
|
||||||
react_remove_properties::remove_properties,
|
react_remove_properties::remove_properties,
|
||||||
react_server_components::server_components,
|
react_server_components::server_components,
|
||||||
remove_console::remove_console,
|
remove_console::remove_console,
|
||||||
server_actions::{self, server_actions},
|
server_actions::{
|
||||||
|
server_actions, {self},
|
||||||
|
},
|
||||||
shake_exports::{shake_exports, Config as ShakeExportsConfig},
|
shake_exports::{shake_exports, Config as ShakeExportsConfig},
|
||||||
};
|
};
|
||||||
use next_transform_font::{next_font_loaders, Config as FontLoaderConfig};
|
use next_transform_font::{next_font_loaders, Config as FontLoaderConfig};
|
||||||
|
|
|
@ -7,17 +7,17 @@ use napi::{
|
||||||
JsFunction,
|
JsFunction,
|
||||||
};
|
};
|
||||||
use next_core::app_structure::{
|
use next_core::app_structure::{
|
||||||
find_app_dir, get_entrypoints as get_entrypoints_impl, Components, ComponentsVc, Entrypoint,
|
find_app_dir, get_entrypoints as get_entrypoints_impl, Components, Entrypoint, Entrypoints,
|
||||||
EntrypointsVc, LoaderTree, LoaderTreeVc, MetadataWithAltItem,
|
LoaderTree, MetadataWithAltItem,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use turbo_tasks::{unit, ReadRef, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{
|
turbo::{
|
||||||
tasks::{
|
tasks::{
|
||||||
debug::ValueDebugFormat, primitives::StringsVc, trace::TraceRawVcs, NothingVc,
|
debug::ValueDebugFormat, trace::TraceRawVcs, TryJoinIterExt, TurboTasks, ValueToString,
|
||||||
TryJoinIterExt, TurboTasks, ValueToString,
|
|
||||||
},
|
},
|
||||||
tasks_fs::{DiskFileSystemVc, FileSystem, FileSystemPathVc, FileSystemVc},
|
tasks_fs::{DiskFileSystem, FileSystem, FileSystemPath},
|
||||||
tasks_memory::MemoryBackend,
|
tasks_memory::MemoryBackend,
|
||||||
},
|
},
|
||||||
turbopack::core::PROJECT_FILESYSTEM_NAME,
|
turbopack::core::PROJECT_FILESYSTEM_NAME,
|
||||||
|
@ -26,20 +26,19 @@ use turbopack_binding::{
|
||||||
use crate::register;
|
use crate::register;
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn project_fs(project_dir: &str, watching: bool) -> Result<FileSystemVc> {
|
async fn project_fs(project_dir: String, watching: bool) -> Result<Vc<Box<dyn FileSystem>>> {
|
||||||
let disk_fs =
|
let disk_fs = DiskFileSystem::new(PROJECT_FILESYSTEM_NAME.to_string(), project_dir.to_string());
|
||||||
DiskFileSystemVc::new(PROJECT_FILESYSTEM_NAME.to_string(), project_dir.to_string());
|
|
||||||
if watching {
|
if watching {
|
||||||
disk_fs.await?.start_watching_with_invalidation_reason()?;
|
disk_fs.await?.start_watching_with_invalidation_reason()?;
|
||||||
}
|
}
|
||||||
Ok(disk_fs.into())
|
Ok(Vc::upcast(disk_fs))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
struct LoaderTreeForJs {
|
struct LoaderTreeForJs {
|
||||||
segment: String,
|
segment: String,
|
||||||
parallel_routes: HashMap<String, LoaderTreeForJsReadRef>,
|
parallel_routes: HashMap<String, ReadRef<LoaderTreeForJs>>,
|
||||||
#[turbo_tasks(trace_ignore)]
|
#[turbo_tasks(trace_ignore)]
|
||||||
components: ComponentsForJs,
|
components: ComponentsForJs,
|
||||||
}
|
}
|
||||||
|
@ -47,8 +46,12 @@ struct LoaderTreeForJs {
|
||||||
#[derive(PartialEq, Eq, Serialize, Deserialize, ValueDebugFormat, TraceRawVcs)]
|
#[derive(PartialEq, Eq, Serialize, Deserialize, ValueDebugFormat, TraceRawVcs)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
enum EntrypointForJs {
|
enum EntrypointForJs {
|
||||||
AppPage { loader_tree: LoaderTreeForJsReadRef },
|
AppPage {
|
||||||
AppRoute { path: String },
|
loader_tree: ReadRef<LoaderTreeForJs>,
|
||||||
|
},
|
||||||
|
AppRoute {
|
||||||
|
path: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(transparent)]
|
#[turbo_tasks::value(transparent)]
|
||||||
|
@ -56,9 +59,12 @@ enum EntrypointForJs {
|
||||||
struct EntrypointsForJs(HashMap<String, EntrypointForJs>);
|
struct EntrypointsForJs(HashMap<String, EntrypointForJs>);
|
||||||
|
|
||||||
#[turbo_tasks::value(transparent)]
|
#[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?) {
|
match project_path.await?.get_path_to(&*path.await?) {
|
||||||
None => Err(anyhow!(
|
None => Err(anyhow!(
|
||||||
"Path {} is not inside of the project path {}",
|
"Path {} is not inside of the project path {}",
|
||||||
|
@ -119,8 +125,8 @@ enum MetadataForJsItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn prepare_components_for_js(
|
async fn prepare_components_for_js(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
components: ComponentsVc,
|
components: Vc<Components>,
|
||||||
) -> Result<ComponentsForJs> {
|
) -> Result<ComponentsForJs> {
|
||||||
let Components {
|
let Components {
|
||||||
page,
|
page,
|
||||||
|
@ -136,8 +142,8 @@ async fn prepare_components_for_js(
|
||||||
let mut result = ComponentsForJs::default();
|
let mut result = ComponentsForJs::default();
|
||||||
async fn add(
|
async fn add(
|
||||||
result: &mut Option<String>,
|
result: &mut Option<String>,
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
value: &Option<FileSystemPathVc>,
|
value: &Option<Vc<FileSystemPath>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
*result = Some(fs_path_to_path(project_path, *value).await?);
|
*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?;
|
add(&mut result.route, project_path, route).await?;
|
||||||
async fn add_meta<'a>(
|
async fn add_meta<'a>(
|
||||||
meta: &mut Vec<MetadataForJsItem>,
|
meta: &mut Vec<MetadataForJsItem>,
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
value: impl Iterator<Item = &'a MetadataWithAltItem>,
|
value: impl Iterator<Item = &'a MetadataWithAltItem>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut value = value.peekable();
|
let mut value = value.peekable();
|
||||||
|
@ -198,9 +204,9 @@ async fn prepare_components_for_js(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn prepare_loader_tree_for_js(
|
async fn prepare_loader_tree_for_js(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
loader_tree: LoaderTreeVc,
|
loader_tree: Vc<LoaderTree>,
|
||||||
) -> Result<LoaderTreeForJsVc> {
|
) -> Result<Vc<LoaderTreeForJs>> {
|
||||||
let LoaderTree {
|
let LoaderTree {
|
||||||
segment,
|
segment,
|
||||||
parallel_routes,
|
parallel_routes,
|
||||||
|
@ -229,9 +235,9 @@ async fn prepare_loader_tree_for_js(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn prepare_entrypoints_for_js(
|
async fn prepare_entrypoints_for_js(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
entrypoints: EntrypointsVc,
|
entrypoints: Vc<Entrypoints>,
|
||||||
) -> Result<EntrypointsForJsVc> {
|
) -> Result<Vc<EntrypointsForJs>> {
|
||||||
let entrypoints = entrypoints
|
let entrypoints = entrypoints
|
||||||
.await?
|
.await?
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -253,24 +259,24 @@ async fn prepare_entrypoints_for_js(
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
Ok(EntrypointsForJsVc::cell(entrypoints))
|
Ok(Vc::cell(entrypoints))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn get_value(
|
async fn get_value(
|
||||||
root_dir: &str,
|
root_dir: String,
|
||||||
project_dir: &str,
|
project_dir: String,
|
||||||
page_extensions: Vec<String>,
|
page_extensions: Vec<String>,
|
||||||
watching: bool,
|
watching: bool,
|
||||||
) -> Result<OptionEntrypointsForJsVc> {
|
) -> Result<Vc<OptionEntrypointsForJs>> {
|
||||||
let page_extensions = StringsVc::cell(page_extensions);
|
let page_extensions = Vc::cell(page_extensions);
|
||||||
let fs = project_fs(root_dir, watching);
|
let fs = project_fs(root_dir.clone(), watching);
|
||||||
let project_relative = project_dir.strip_prefix(root_dir).unwrap();
|
let project_relative = project_dir.strip_prefix(&root_dir).unwrap();
|
||||||
let project_relative = project_relative
|
let project_relative = project_relative
|
||||||
.strip_prefix(MAIN_SEPARATOR)
|
.strip_prefix(MAIN_SEPARATOR)
|
||||||
.unwrap_or(project_relative)
|
.unwrap_or(project_relative)
|
||||||
.replace(MAIN_SEPARATOR, "/");
|
.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);
|
let app_dir = find_app_dir(project_path);
|
||||||
|
|
||||||
|
@ -283,7 +289,7 @@ async fn get_value(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(OptionEntrypointsForJsVc::cell(result))
|
Ok(Vc::cell(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
|
@ -295,7 +301,7 @@ pub fn stream_entrypoints(
|
||||||
func: JsFunction,
|
func: JsFunction,
|
||||||
) -> napi::Result<()> {
|
) -> napi::Result<()> {
|
||||||
register();
|
register();
|
||||||
let func: ThreadsafeFunction<Option<EntrypointsForJsReadRef>, ErrorStrategy::CalleeHandled> =
|
let func: ThreadsafeFunction<Option<ReadRef<EntrypointsForJs>>, ErrorStrategy::CalleeHandled> =
|
||||||
func.create_threadsafe_function(0, |ctx| {
|
func.create_threadsafe_function(0, |ctx| {
|
||||||
let value = ctx.value;
|
let value = ctx.value;
|
||||||
let value = serde_json::to_value(value)?;
|
let value = serde_json::to_value(value)?;
|
||||||
|
@ -305,16 +311,14 @@ pub fn stream_entrypoints(
|
||||||
let project_dir = Arc::new(project_dir);
|
let project_dir = Arc::new(project_dir);
|
||||||
let page_extensions = Arc::new(page_extensions);
|
let page_extensions = Arc::new(page_extensions);
|
||||||
turbo_tasks.spawn_root_task(move || {
|
turbo_tasks.spawn_root_task(move || {
|
||||||
let func: ThreadsafeFunction<
|
let func: ThreadsafeFunction<Option<ReadRef<EntrypointsForJs>>> = func.clone();
|
||||||
Option<turbo_tasks::ReadRef<EntrypointsForJs, HashMap<String, EntrypointForJs>>>,
|
|
||||||
> = func.clone();
|
|
||||||
let project_dir = project_dir.clone();
|
let project_dir = project_dir.clone();
|
||||||
let root_dir = root_dir.clone();
|
let root_dir = root_dir.clone();
|
||||||
let page_extensions: Arc<Vec<String>> = page_extensions.clone();
|
let page_extensions: Arc<Vec<String>> = page_extensions.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
if let Some(entrypoints) = &*get_value(
|
if let Some(entrypoints) = &*get_value(
|
||||||
&root_dir,
|
(*root_dir).clone(),
|
||||||
&project_dir,
|
(*project_dir).clone(),
|
||||||
page_extensions.iter().map(|s| s.to_string()).collect(),
|
page_extensions.iter().map(|s| s.to_string()).collect(),
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
@ -328,7 +332,7 @@ pub fn stream_entrypoints(
|
||||||
func.call(Ok(None), ThreadsafeFunctionCallMode::NonBlocking);
|
func.call(Ok(None), ThreadsafeFunctionCallMode::NonBlocking);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(NothingVc::new().into())
|
Ok(unit().node)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -345,8 +349,8 @@ pub async fn get_entrypoints(
|
||||||
let result = turbo_tasks
|
let result = turbo_tasks
|
||||||
.run_once(async move {
|
.run_once(async move {
|
||||||
let value = if let Some(entrypoints) = &*get_value(
|
let value = if let Some(entrypoints) = &*get_value(
|
||||||
&root_dir,
|
root_dir,
|
||||||
&project_dir,
|
project_dir,
|
||||||
page_extensions.iter().map(|s| s.to_string()).collect(),
|
page_extensions.iter().map(|s| s.to_string()).collect(),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
|
|
|
@ -28,6 +28,8 @@ DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#![recursion_limit = "2048"]
|
#![recursion_limit = "2048"]
|
||||||
//#![deny(clippy::all)]
|
//#![deny(clippy::all)]
|
||||||
|
#![feature(arbitrary_self_types)]
|
||||||
|
#![feature(async_fn_in_trait)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate napi_derive;
|
extern crate napi_derive;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
use napi::{bindgen_prelude::External, JsFunction};
|
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 turbopack_binding::turbopack::core::error::PrettyPrintError;
|
||||||
|
|
||||||
use super::utils::{subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc};
|
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]
|
#[napi]
|
||||||
pub async fn endpoint_write_to_disk(
|
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> {
|
) -> napi::Result<NapiWrittenEndpoint> {
|
||||||
let turbo_tasks = endpoint.turbo_tasks().clone();
|
let turbo_tasks = endpoint.turbo_tasks().clone();
|
||||||
let endpoint = **endpoint;
|
let endpoint = ***endpoint;
|
||||||
let written = turbo_tasks
|
let written = turbo_tasks
|
||||||
.run_once(async move { endpoint.write_to_disk().strongly_consistent().await })
|
.run_once(async move { endpoint.write_to_disk().strongly_consistent().await })
|
||||||
.await
|
.await
|
||||||
|
@ -39,7 +58,9 @@ pub async fn endpoint_write_to_disk(
|
||||||
|
|
||||||
#[napi(ts_return_type = "{ __napiType: \"RootTask\" }")]
|
#[napi(ts_return_type = "{ __napiType: \"RootTask\" }")]
|
||||||
pub fn endpoint_changed_subscribe(
|
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,
|
func: JsFunction,
|
||||||
) -> napi::Result<External<RootTask>> {
|
) -> napi::Result<External<RootTask>> {
|
||||||
let turbo_tasks = endpoint.turbo_tasks().clone();
|
let turbo_tasks = endpoint.turbo_tasks().clone();
|
||||||
|
|
|
@ -3,15 +3,18 @@ use std::sync::Arc;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use napi::{bindgen_prelude::External, JsFunction};
|
use napi::{bindgen_prelude::External, JsFunction};
|
||||||
use next_api::{
|
use next_api::{
|
||||||
project::{Middleware, ProjectOptions, ProjectVc},
|
project::{Middleware, Project, ProjectOptions},
|
||||||
route::{EndpointVc, Route},
|
route::{Endpoint, Route},
|
||||||
};
|
};
|
||||||
use turbo_tasks::TurboTasks;
|
use turbo_tasks::{TurboTasks, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_memory::MemoryBackend, turbopack::core::error::PrettyPrintError,
|
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;
|
use crate::register;
|
||||||
|
|
||||||
#[napi(object)]
|
#[napi(object)]
|
||||||
|
@ -46,7 +49,9 @@ impl From<NapiProjectOptions> for ProjectOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi(ts_return_type = "{ __napiType: \"Project\" }")]
|
#[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();
|
register();
|
||||||
let turbo_tasks = TurboTasks::new(MemoryBackend::new(
|
let turbo_tasks = TurboTasks::new(MemoryBackend::new(
|
||||||
options
|
options
|
||||||
|
@ -56,7 +61,7 @@ pub async fn project_new(options: NapiProjectOptions) -> napi::Result<External<V
|
||||||
));
|
));
|
||||||
let options = options.into();
|
let options = options.into();
|
||||||
let project = turbo_tasks
|
let project = turbo_tasks
|
||||||
.run_once(async move { ProjectVc::new(options).resolve().await })
|
.run_once(async move { Project::new(options).resolve().await })
|
||||||
.await
|
.await
|
||||||
.map_err(|e| napi::Error::from_reason(PrettyPrintError(&e).to_string()))?;
|
.map_err(|e| napi::Error::from_reason(PrettyPrintError(&e).to_string()))?;
|
||||||
Ok(External::new_with_size_hint(
|
Ok(External::new_with_size_hint(
|
||||||
|
@ -75,10 +80,10 @@ struct NapiRoute {
|
||||||
pub r#type: &'static str,
|
pub r#type: &'static str,
|
||||||
|
|
||||||
// Different representations of the endpoint
|
// Different representations of the endpoint
|
||||||
pub endpoint: Option<External<VcArc<EndpointVc>>>,
|
pub endpoint: Option<External<ExternalEndpoint>>,
|
||||||
pub html_endpoint: Option<External<VcArc<EndpointVc>>>,
|
pub html_endpoint: Option<External<ExternalEndpoint>>,
|
||||||
pub rsc_endpoint: Option<External<VcArc<EndpointVc>>>,
|
pub rsc_endpoint: Option<External<ExternalEndpoint>>,
|
||||||
pub data_endpoint: Option<External<VcArc<EndpointVc>>>,
|
pub data_endpoint: Option<External<ExternalEndpoint>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NapiRoute {
|
impl NapiRoute {
|
||||||
|
@ -87,8 +92,12 @@ impl NapiRoute {
|
||||||
value: Route,
|
value: Route,
|
||||||
turbo_tasks: &Arc<TurboTasks<MemoryBackend>>,
|
turbo_tasks: &Arc<TurboTasks<MemoryBackend>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let convert_endpoint =
|
let convert_endpoint = |endpoint: Vc<Box<dyn Endpoint>>| {
|
||||||
|endpoint: EndpointVc| Some(External::new(VcArc::new(turbo_tasks.clone(), endpoint)));
|
Some(External::new(ExternalEndpoint(VcArc::new(
|
||||||
|
turbo_tasks.clone(),
|
||||||
|
endpoint,
|
||||||
|
))))
|
||||||
|
};
|
||||||
match value {
|
match value {
|
||||||
Route::Page {
|
Route::Page {
|
||||||
html_endpoint,
|
html_endpoint,
|
||||||
|
@ -133,7 +142,7 @@ impl NapiRoute {
|
||||||
|
|
||||||
#[napi(object)]
|
#[napi(object)]
|
||||||
struct NapiMiddleware {
|
struct NapiMiddleware {
|
||||||
pub endpoint: External<VcArc<EndpointVc>>,
|
pub endpoint: External<VcArc<Vc<Box<dyn Endpoint>>>>,
|
||||||
pub runtime: String,
|
pub runtime: String,
|
||||||
pub matcher: Option<Vec<String>>,
|
pub matcher: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
@ -161,7 +170,7 @@ struct NapiEntrypoints {
|
||||||
|
|
||||||
#[napi(ts_return_type = "{ __napiType: \"RootTask\" }")]
|
#[napi(ts_return_type = "{ __napiType: \"RootTask\" }")]
|
||||||
pub fn project_entrypoints_subscribe(
|
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,
|
func: JsFunction,
|
||||||
) -> napi::Result<External<RootTask>> {
|
) -> napi::Result<External<RootTask>> {
|
||||||
let turbo_tasks = project.turbo_tasks().clone();
|
let turbo_tasks = project.turbo_tasks().clone();
|
||||||
|
|
|
@ -7,7 +7,7 @@ use napi::{
|
||||||
JsFunction, JsObject, NapiRaw, NapiValue, Status,
|
JsFunction, JsObject, NapiRaw, NapiValue, Status,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use turbo_tasks::{NothingVc, TaskId, TurboTasks};
|
use turbo_tasks::{unit, TaskId, TurboTasks};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_memory::MemoryBackend, turbopack::core::error::PrettyPrintError,
|
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);
|
eprintln!("{}", error);
|
||||||
return Err(error);
|
return Err(error);
|
||||||
}
|
}
|
||||||
Ok(NothingVc::new().into())
|
Ok(unit().node)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
Ok(External::new(RootTask {
|
Ok(External::new(RootTask {
|
||||||
|
|
|
@ -31,7 +31,13 @@ use std::{cell::RefCell, env, path::PathBuf};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use napi::bindgen_prelude::{External, Status};
|
use napi::bindgen_prelude::{External, Status};
|
||||||
#[cfg(feature = "crash-report")]
|
#[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_chrome::{ChromeLayerBuilder, FlushGuard};
|
||||||
use tracing_subscriber::{filter, prelude::*, util::SubscriberInitExt, Layer};
|
use tracing_subscriber::{filter, prelude::*, util::SubscriberInitExt, Layer};
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,28 @@
|
||||||
use next_core::app_structure::Entrypoint;
|
use next_core::app_structure::Entrypoint;
|
||||||
use serde::{Deserialize, Serialize};
|
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]
|
#[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 {
|
match entrypoint {
|
||||||
Entrypoint::AppPage { .. } => Route::AppPage {
|
Entrypoint::AppPage { .. } => Route::AppPage {
|
||||||
html_endpoint: AppPageEndpoint {
|
html_endpoint: Vc::upcast(
|
||||||
ty: AppPageEndpointType::Html,
|
AppPageEndpoint {
|
||||||
}
|
ty: AppPageEndpointType::Html,
|
||||||
.cell()
|
}
|
||||||
.into(),
|
.cell(),
|
||||||
rsc_endpoint: AppPageEndpoint {
|
),
|
||||||
ty: AppPageEndpointType::Rsc,
|
rsc_endpoint: Vc::upcast(
|
||||||
}
|
AppPageEndpoint {
|
||||||
.cell()
|
ty: AppPageEndpointType::Rsc,
|
||||||
.into(),
|
}
|
||||||
|
.cell(),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
Entrypoint::AppRoute { .. } => Route::AppRoute {
|
Entrypoint::AppRoute { .. } => Route::AppRoute {
|
||||||
endpoint: AppRouteEndpoint.cell().into(),
|
endpoint: Vc::upcast(AppRouteEndpoint.cell()),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
|
@ -40,12 +42,12 @@ struct AppPageEndpoint {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Endpoint for AppPageEndpoint {
|
impl Endpoint for AppPageEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn write_to_disk(&self) -> WrittenEndpointVc {
|
fn write_to_disk(&self) -> Vc<WrittenEndpoint> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn changed(&self) -> CompletionVc {
|
fn changed(&self) -> Vc<Completion> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,12 +58,12 @@ struct AppRouteEndpoint;
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Endpoint for AppRouteEndpoint {
|
impl Endpoint for AppRouteEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn write_to_disk(&self) -> WrittenEndpointVc {
|
fn write_to_disk(&self) -> Vc<WrittenEndpoint> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn changed(&self) -> CompletionVc {
|
fn changed(&self) -> Vc<Completion> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#![feature(future_join)]
|
#![feature(future_join)]
|
||||||
#![feature(min_specialization)]
|
#![feature(arbitrary_self_types)]
|
||||||
|
#![feature(async_fn_in_trait)]
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod pages;
|
mod pages;
|
||||||
|
|
|
@ -2,45 +2,42 @@ use anyhow::{bail, Context, Result};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use next_core::{
|
use next_core::{
|
||||||
create_page_loader_entry_module, emit_all_assets, get_asset_path_from_pathname,
|
create_page_loader_entry_module, emit_all_assets, get_asset_path_from_pathname,
|
||||||
pages_structure::{
|
pages_structure::{PagesDirectoryStructure, PagesStructure, PagesStructureItem},
|
||||||
PagesDirectoryStructure, PagesDirectoryStructureVc, PagesStructure, PagesStructureItem,
|
|
||||||
PagesStructureVc,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use turbo_tasks::{primitives::StringVc, CompletionVc, CompletionsVc, Value};
|
use turbo_tasks::{Completion, Completions, Value, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::FileSystemPathVc,
|
turbo::tasks_fs::FileSystemPath,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::Asset,
|
asset::Asset,
|
||||||
changed::{any_content_changed, any_content_changed_of_output_assets},
|
changed::{any_content_changed, any_content_changed_of_output_assets},
|
||||||
chunk::{ChunkableModule, ChunkingContext},
|
chunk::{ChunkableModule, ChunkingContext},
|
||||||
context::AssetContext,
|
context::AssetContext,
|
||||||
file_source::FileSourceVc,
|
file_source::FileSource,
|
||||||
output::{OutputAssetVc, OutputAssetsVc},
|
output::{OutputAsset, OutputAssets},
|
||||||
reference_type::{EntryReferenceSubType, ReferenceType},
|
reference_type::{EntryReferenceSubType, ReferenceType},
|
||||||
source::SourceVc,
|
source::Source,
|
||||||
},
|
},
|
||||||
ecmascript::EcmascriptModuleAssetVc,
|
ecmascript::EcmascriptModuleAsset,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
project::ProjectVc,
|
project::Project,
|
||||||
route::{Endpoint, EndpointVc, Route, RoutesVc, WrittenEndpoint, WrittenEndpointVc},
|
route::{Endpoint, Route, Routes, WrittenEndpoint},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_pages_routes(
|
pub async fn get_pages_routes(
|
||||||
project: ProjectVc,
|
project: Vc<Project>,
|
||||||
page_structure: PagesStructureVc,
|
page_structure: Vc<PagesStructure>,
|
||||||
) -> Result<RoutesVc> {
|
) -> Result<Vc<Routes>> {
|
||||||
let PagesStructure { api, pages, .. } = *page_structure.await?;
|
let PagesStructure { api, pages, .. } = *page_structure.await?;
|
||||||
let mut routes = IndexMap::new();
|
let mut routes = IndexMap::new();
|
||||||
async fn add_dir_to_routes(
|
async fn add_dir_to_routes(
|
||||||
routes: &mut IndexMap<String, Route>,
|
routes: &mut IndexMap<String, Route>,
|
||||||
dir: PagesDirectoryStructureVc,
|
dir: Vc<PagesDirectoryStructure>,
|
||||||
make_route: impl Fn(StringVc, StringVc, FileSystemPathVc) -> Route,
|
make_route: impl Fn(Vc<String>, Vc<String>, Vc<FileSystemPath>) -> Route,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut queue = vec![dir];
|
let mut queue = vec![dir];
|
||||||
while let Some(dir) = queue.pop() {
|
while let Some(dir) = queue.pop() {
|
||||||
|
@ -57,8 +54,8 @@ pub async fn get_pages_routes(
|
||||||
original_path,
|
original_path,
|
||||||
} = *item.await?;
|
} = *item.await?;
|
||||||
let pathname = format!("/{}", next_router_path.await?.path);
|
let pathname = format!("/{}", next_router_path.await?.path);
|
||||||
let pathname_vc = StringVc::cell(pathname.clone());
|
let pathname_vc = Vc::cell(pathname.clone());
|
||||||
let original_name = StringVc::cell(format!("/{}", original_path.await?.path));
|
let original_name = Vc::cell(format!("/{}", original_path.await?.path));
|
||||||
let route = make_route(pathname_vc, original_name, project_path);
|
let route = make_route(pathname_vc, original_name, project_path);
|
||||||
routes.insert(pathname, route);
|
routes.insert(pathname, route);
|
||||||
}
|
}
|
||||||
|
@ -71,7 +68,7 @@ pub async fn get_pages_routes(
|
||||||
if let Some(api) = api {
|
if let Some(api) = api {
|
||||||
add_dir_to_routes(&mut routes, api, |pathname, original_name, path| {
|
add_dir_to_routes(&mut routes, api, |pathname, original_name, path| {
|
||||||
Route::PageApi {
|
Route::PageApi {
|
||||||
endpoint: ApiEndpointVc::new(project, pathname, original_name, path).into(),
|
endpoint: Vc::upcast(ApiEndpoint::new(project, pathname, original_name, path)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -79,34 +76,42 @@ pub async fn get_pages_routes(
|
||||||
if let Some(page) = pages {
|
if let Some(page) = pages {
|
||||||
add_dir_to_routes(&mut routes, page, |pathname, original_name, path| {
|
add_dir_to_routes(&mut routes, page, |pathname, original_name, path| {
|
||||||
Route::Page {
|
Route::Page {
|
||||||
html_endpoint: PageHtmlEndpointVc::new(project, pathname, original_name, path)
|
html_endpoint: Vc::upcast(PageHtmlEndpoint::new(
|
||||||
.into(),
|
project,
|
||||||
data_endpoint: PageDataEndpointVc::new(project, pathname, original_name, path)
|
pathname,
|
||||||
.into(),
|
original_name,
|
||||||
|
path,
|
||||||
|
)),
|
||||||
|
data_endpoint: Vc::upcast(PageDataEndpoint::new(
|
||||||
|
project,
|
||||||
|
pathname,
|
||||||
|
original_name,
|
||||||
|
path,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
Ok(RoutesVc::cell(routes))
|
Ok(Vc::cell(routes))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct PageHtmlEndpoint {
|
struct PageHtmlEndpoint {
|
||||||
project: ProjectVc,
|
project: Vc<Project>,
|
||||||
pathname: StringVc,
|
pathname: Vc<String>,
|
||||||
original_name: StringVc,
|
original_name: Vc<String>,
|
||||||
path: FileSystemPathVc,
|
path: Vc<FileSystemPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl PageHtmlEndpointVc {
|
impl PageHtmlEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn new(
|
fn new(
|
||||||
project: ProjectVc,
|
project: Vc<Project>,
|
||||||
pathname: StringVc,
|
pathname: Vc<String>,
|
||||||
original_name: StringVc,
|
original_name: Vc<String>,
|
||||||
path: FileSystemPathVc,
|
path: Vc<FileSystemPath>,
|
||||||
) -> Self {
|
) -> Vc<Self> {
|
||||||
PageHtmlEndpoint {
|
PageHtmlEndpoint {
|
||||||
project,
|
project,
|
||||||
pathname,
|
pathname,
|
||||||
|
@ -117,13 +122,13 @@ impl PageHtmlEndpointVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn source(self) -> Result<SourceVc> {
|
async fn source(self: Vc<Self>) -> Result<Vc<Box<dyn Source>>> {
|
||||||
let this = self.await?;
|
let this = self.await?;
|
||||||
Ok(FileSourceVc::new(this.path).into())
|
Ok(Vc::upcast(FileSource::new(this.path)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
|
|
||||||
let client_module = create_page_loader_entry_module(
|
let client_module = create_page_loader_entry_module(
|
||||||
|
@ -132,27 +137,28 @@ impl PageHtmlEndpointVc {
|
||||||
this.pathname,
|
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 {
|
else {
|
||||||
bail!("expected an ECMAScript module asset");
|
bail!("expected an ECMAScript module asset");
|
||||||
};
|
};
|
||||||
|
|
||||||
let client_chunking_context = this.project.client_chunking_context();
|
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(
|
let client_chunks = client_chunking_context.evaluated_chunk_group(
|
||||||
client_entry_chunk,
|
client_entry_chunk,
|
||||||
this.project
|
this.project
|
||||||
.pages_client_runtime_entries()
|
.pages_client_runtime_entries()
|
||||||
.with_entry(client_module.into()),
|
.with_entry(Vc::upcast(client_module)),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(client_chunks)
|
Ok(client_chunks)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
||||||
|
|
||||||
|
@ -161,17 +167,19 @@ impl PageHtmlEndpointVc {
|
||||||
.pages_ssr_module_context()
|
.pages_ssr_module_context()
|
||||||
.process(self.source(), reference_type.clone());
|
.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");
|
bail!("expected an ECMAScript module asset");
|
||||||
};
|
};
|
||||||
|
|
||||||
let asset_path = get_asset_path_from_pathname(&this.pathname.await?, ".js");
|
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_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(
|
let ssr_entry_chunk = this.project.ssr_chunking_context().entry_chunk(
|
||||||
ssr_entry_chunk_path,
|
ssr_entry_chunk_path,
|
||||||
ssr_module.into(),
|
Vc::upcast(ssr_module),
|
||||||
this.project.pages_ssr_runtime_entries(),
|
this.project.pages_ssr_runtime_entries(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -182,19 +190,19 @@ impl PageHtmlEndpointVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Endpoint for PageHtmlEndpoint {
|
impl Endpoint for PageHtmlEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn write_to_disk(self_vc: PageHtmlEndpointVc) -> Result<WrittenEndpointVc> {
|
async fn write_to_disk(self: Vc<Self>) -> Result<Vc<WrittenEndpoint>> {
|
||||||
let this = self_vc.await?;
|
let this = self.await?;
|
||||||
let ssr_chunk = self_vc.ssr_chunk();
|
let ssr_chunk = self.ssr_chunk();
|
||||||
let ssr_emit = emit_all_assets(
|
let ssr_emit = emit_all_assets(
|
||||||
OutputAssetsVc::cell(vec![ssr_chunk]),
|
Vc::cell(vec![ssr_chunk]),
|
||||||
this.project.node_root(),
|
this.project.node_root(),
|
||||||
this.project.client_root().join("_next"),
|
this.project.client_root().join("_next".to_string()),
|
||||||
this.project.node_root(),
|
this.project.node_root(),
|
||||||
);
|
);
|
||||||
let client_emit = emit_all_assets(
|
let client_emit = emit_all_assets(
|
||||||
self_vc.client_chunks(),
|
self.client_chunks(),
|
||||||
this.project.node_root(),
|
this.project.node_root(),
|
||||||
this.project.client_root().join("_next"),
|
this.project.client_root().join("_next".to_string()),
|
||||||
this.project.node_root(),
|
this.project.node_root(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -215,32 +223,32 @@ impl Endpoint for PageHtmlEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn changed(self_vc: PageHtmlEndpointVc) -> CompletionVc {
|
fn changed(self: Vc<Self>) -> Vc<Completion> {
|
||||||
let ssr_chunk = self_vc.ssr_chunk();
|
let ssr_chunk = self.ssr_chunk();
|
||||||
CompletionsVc::all(vec![
|
Completions::all(vec![
|
||||||
any_content_changed(ssr_chunk.into()),
|
any_content_changed(Vc::upcast(ssr_chunk)),
|
||||||
any_content_changed_of_output_assets(self_vc.client_chunks()),
|
any_content_changed_of_output_assets(self.client_chunks()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct PageDataEndpoint {
|
struct PageDataEndpoint {
|
||||||
project: ProjectVc,
|
project: Vc<Project>,
|
||||||
pathname: StringVc,
|
pathname: Vc<String>,
|
||||||
original_name: StringVc,
|
original_name: Vc<String>,
|
||||||
path: FileSystemPathVc,
|
path: Vc<FileSystemPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl PageDataEndpointVc {
|
impl PageDataEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn new(
|
fn new(
|
||||||
project: ProjectVc,
|
project: Vc<Project>,
|
||||||
pathname: StringVc,
|
pathname: Vc<String>,
|
||||||
original_name: StringVc,
|
original_name: Vc<String>,
|
||||||
path: FileSystemPathVc,
|
path: Vc<FileSystemPath>,
|
||||||
) -> Self {
|
) -> Vc<Self> {
|
||||||
PageDataEndpoint {
|
PageDataEndpoint {
|
||||||
project,
|
project,
|
||||||
pathname,
|
pathname,
|
||||||
|
@ -251,13 +259,13 @@ impl PageDataEndpointVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn source(self) -> Result<SourceVc> {
|
async fn source(self: Vc<Self>) -> Result<Vc<Box<dyn Source>>> {
|
||||||
let this = self.await?;
|
let this = self.await?;
|
||||||
Ok(FileSourceVc::new(this.path).into())
|
Ok(Vc::upcast(FileSource::new(this.path)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
||||||
|
|
||||||
|
@ -266,7 +274,8 @@ impl PageDataEndpointVc {
|
||||||
.pages_ssr_data_module_context()
|
.pages_ssr_data_module_context()
|
||||||
.process(self.source(), reference_type.clone());
|
.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 {
|
else {
|
||||||
bail!("expected an ECMAScript module asset");
|
bail!("expected an ECMAScript module asset");
|
||||||
};
|
};
|
||||||
|
@ -277,10 +286,10 @@ impl PageDataEndpointVc {
|
||||||
let ssr_data_entry_chunk_path = this
|
let ssr_data_entry_chunk_path = this
|
||||||
.project
|
.project
|
||||||
.node_root()
|
.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(
|
let ssr_data_entry_chunk = this.project.ssr_data_chunking_context().entry_chunk(
|
||||||
ssr_data_entry_chunk_path,
|
ssr_data_entry_chunk_path,
|
||||||
ssr_data_module.into(),
|
Vc::upcast(ssr_data_module),
|
||||||
this.project.pages_ssr_runtime_entries(),
|
this.project.pages_ssr_runtime_entries(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -291,13 +300,13 @@ impl PageDataEndpointVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Endpoint for PageDataEndpoint {
|
impl Endpoint for PageDataEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn write_to_disk(self_vc: PageDataEndpointVc) -> Result<WrittenEndpointVc> {
|
async fn write_to_disk(self: Vc<Self>) -> Result<Vc<WrittenEndpoint>> {
|
||||||
let this = self_vc.await?;
|
let this = self.await?;
|
||||||
let ssr_data_chunk = self_vc.ssr_data_chunk();
|
let ssr_data_chunk = self.ssr_data_chunk();
|
||||||
emit_all_assets(
|
emit_all_assets(
|
||||||
OutputAssetsVc::cell(vec![ssr_data_chunk]),
|
Vc::cell(vec![ssr_data_chunk]),
|
||||||
this.project.node_root(),
|
this.project.node_root(),
|
||||||
this.project.client_root().join("_next"),
|
this.project.client_root().join("_next".to_string()),
|
||||||
this.project.node_root(),
|
this.project.node_root(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -316,29 +325,29 @@ impl Endpoint for PageDataEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn changed(self_vc: PageDataEndpointVc) -> Result<CompletionVc> {
|
async fn changed(self: Vc<Self>) -> Result<Vc<Completion>> {
|
||||||
let ssr_data_chunk = self_vc.ssr_data_chunk();
|
let ssr_data_chunk = self.ssr_data_chunk();
|
||||||
Ok(any_content_changed(ssr_data_chunk.into()))
|
Ok(any_content_changed(Vc::upcast(ssr_data_chunk)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct ApiEndpoint {
|
struct ApiEndpoint {
|
||||||
project: ProjectVc,
|
project: Vc<Project>,
|
||||||
pathname: StringVc,
|
pathname: Vc<String>,
|
||||||
original_name: StringVc,
|
original_name: Vc<String>,
|
||||||
path: FileSystemPathVc,
|
path: Vc<FileSystemPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ApiEndpointVc {
|
impl ApiEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn new(
|
fn new(
|
||||||
project: ProjectVc,
|
project: Vc<Project>,
|
||||||
pathname: StringVc,
|
pathname: Vc<String>,
|
||||||
original_name: StringVc,
|
original_name: Vc<String>,
|
||||||
path: FileSystemPathVc,
|
path: Vc<FileSystemPath>,
|
||||||
) -> Self {
|
) -> Vc<Self> {
|
||||||
ApiEndpoint {
|
ApiEndpoint {
|
||||||
project,
|
project,
|
||||||
pathname,
|
pathname,
|
||||||
|
@ -352,12 +361,12 @@ impl ApiEndpointVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Endpoint for ApiEndpoint {
|
impl Endpoint for ApiEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn write_to_disk(&self) -> WrittenEndpointVc {
|
fn write_to_disk(&self) -> Vc<WrittenEndpoint> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn changed(&self) -> CompletionVc {
|
fn changed(&self) -> Vc<Completion> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,47 +10,45 @@ use next_core::{
|
||||||
get_client_module_options_context, get_client_resolve_options_context,
|
get_client_module_options_context, get_client_resolve_options_context,
|
||||||
get_client_runtime_entries, ClientContextType,
|
get_client_runtime_entries, ClientContextType,
|
||||||
},
|
},
|
||||||
next_config::NextConfigVc,
|
next_config::NextConfig,
|
||||||
next_dynamic::NextDynamicTransitionVc,
|
next_dynamic::NextDynamicTransition,
|
||||||
next_server::{
|
next_server::{
|
||||||
get_server_chunking_context, get_server_compile_time_info,
|
get_server_chunking_context, get_server_compile_time_info,
|
||||||
get_server_module_options_context, get_server_resolve_options_context,
|
get_server_module_options_context, get_server_resolve_options_context,
|
||||||
get_server_runtime_entries, ServerContextType,
|
get_server_runtime_entries, ServerContextType,
|
||||||
},
|
},
|
||||||
pages_structure::{find_pages_structure, PagesStructureVc},
|
pages_structure::{find_pages_structure, PagesStructure},
|
||||||
util::NextSourceConfig,
|
util::NextSourceConfig,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{
|
||||||
debug::ValueDebugFormat, trace::TraceRawVcs, NothingVc, TaskInput, TransientValue,
|
debug::ValueDebugFormat, trace::TraceRawVcs, unit, TaskInput, TransientValue, TryJoinIterExt,
|
||||||
TryJoinIterExt, Value,
|
Value, Vc,
|
||||||
};
|
};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{
|
turbo::{
|
||||||
tasks_env::ProcessEnvVc,
|
tasks_env::ProcessEnv,
|
||||||
tasks_fs::{
|
tasks_fs::{DiskFileSystem, FileSystem, FileSystemPath, VirtualFileSystem},
|
||||||
DiskFileSystemVc, FileSystem, FileSystemPathVc, FileSystemVc, VirtualFileSystemVc,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
build::BuildChunkingContextVc,
|
build::BuildChunkingContext,
|
||||||
core::{
|
core::{
|
||||||
chunk::{ChunkingContext, EvaluatableAssetsVc},
|
chunk::{ChunkingContext, EvaluatableAssets},
|
||||||
compile_time_info::CompileTimeInfoVc,
|
compile_time_info::CompileTimeInfo,
|
||||||
context::AssetContextVc,
|
context::AssetContext,
|
||||||
environment::ServerAddrVc,
|
environment::ServerAddr,
|
||||||
PROJECT_FILESYSTEM_NAME,
|
PROJECT_FILESYSTEM_NAME,
|
||||||
},
|
},
|
||||||
dev::DevChunkingContextVc,
|
dev::DevChunkingContext,
|
||||||
ecmascript::chunk::EcmascriptChunkingContextVc,
|
ecmascript::chunk::EcmascriptChunkingContext,
|
||||||
env::dotenv::load_env,
|
env::dotenv::load_env,
|
||||||
node::execution_context::ExecutionContextVc,
|
node::execution_context::ExecutionContext,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
evaluate_context::node_build_environment,
|
evaluate_context::node_build_environment,
|
||||||
module_options::ModuleOptionsContextVc,
|
module_options::ModuleOptionsContext,
|
||||||
resolve_options_context::ResolveOptionsContextVc,
|
resolve_options_context::ResolveOptionsContext,
|
||||||
transition::{ContextTransitionVc, TransitionsByNameVc},
|
transition::{ContextTransition, TransitionsByName},
|
||||||
ModuleAssetContextVc,
|
ModuleAssetContext,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -58,7 +56,7 @@ use turbopack_binding::{
|
||||||
use crate::{
|
use crate::{
|
||||||
app::app_entry_point_to_route,
|
app::app_entry_point_to_route,
|
||||||
pages::get_pages_routes,
|
pages::get_pages_routes,
|
||||||
route::{EndpointVc, Route},
|
route::{Endpoint, Route},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, TaskInput)]
|
#[derive(Debug, Serialize, Deserialize, Clone, TaskInput)]
|
||||||
|
@ -83,7 +81,7 @@ pub struct ProjectOptions {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, TraceRawVcs, PartialEq, Eq, ValueDebugFormat)]
|
#[derive(Serialize, Deserialize, TraceRawVcs, PartialEq, Eq, ValueDebugFormat)]
|
||||||
pub struct Middleware {
|
pub struct Middleware {
|
||||||
pub endpoint: EndpointVc,
|
pub endpoint: Vc<Box<dyn Endpoint>>,
|
||||||
pub config: NextSourceConfig,
|
pub config: NextSourceConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +104,7 @@ pub struct Project {
|
||||||
watch: bool,
|
watch: bool,
|
||||||
|
|
||||||
/// Next config.
|
/// Next config.
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
|
|
||||||
browserslist_query: String,
|
browserslist_query: String,
|
||||||
|
|
||||||
|
@ -114,10 +112,10 @@ pub struct Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ProjectVc {
|
impl Project {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn new(options: ProjectOptions) -> Result<Self> {
|
pub async fn new(options: ProjectOptions) -> Result<Vc<Self>> {
|
||||||
let next_config = NextConfigVc::from_string(options.next_config);
|
let next_config = NextConfig::from_string(options.next_config);
|
||||||
Ok(Project {
|
Ok(Project {
|
||||||
root_path: options.root_path,
|
root_path: options.root_path,
|
||||||
project_path: options.project_path,
|
project_path: options.project_path,
|
||||||
|
@ -132,49 +130,49 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let disk_fs = DiskFileSystemVc::new(
|
let disk_fs = DiskFileSystem::new(
|
||||||
PROJECT_FILESYSTEM_NAME.to_string(),
|
PROJECT_FILESYSTEM_NAME.to_string(),
|
||||||
this.root_path.to_string(),
|
this.root_path.to_string(),
|
||||||
);
|
);
|
||||||
if this.watch {
|
if this.watch {
|
||||||
disk_fs.await?.start_watching_with_invalidation_reason()?;
|
disk_fs.await?.start_watching_with_invalidation_reason()?;
|
||||||
}
|
}
|
||||||
Ok(disk_fs.into())
|
Ok(Vc::upcast(disk_fs))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn client_fs(self) -> Result<FileSystemVc> {
|
async fn client_fs(self: Vc<Self>) -> Result<Vc<Box<dyn FileSystem>>> {
|
||||||
let virtual_fs = VirtualFileSystemVc::new();
|
let virtual_fs = VirtualFileSystem::new();
|
||||||
Ok(virtual_fs.into())
|
Ok(Vc::upcast(virtual_fs))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 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()?;
|
disk_fs.await?.start_watching_with_invalidation_reason()?;
|
||||||
Ok(disk_fs.into())
|
Ok(Vc::upcast(disk_fs))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) fn node_root(self) -> FileSystemPathVc {
|
pub(super) fn node_root(self: Vc<Self>) -> Vc<FileSystemPath> {
|
||||||
self.node_fs().root().join(".next")
|
self.node_fs().root().join(".next".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) fn client_root(self) -> FileSystemPathVc {
|
pub(super) fn client_root(self: Vc<Self>) -> Vc<FileSystemPath> {
|
||||||
self.client_fs().root()
|
self.client_fs().root()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn project_root_path(self) -> FileSystemPathVc {
|
fn project_root_path(self: Vc<Self>) -> Vc<FileSystemPath> {
|
||||||
self.project_fs().root()
|
self.project_fs().root()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let root = self.project_root_path();
|
let root = self.project_root_path();
|
||||||
let project_relative = this.project_path.strip_prefix(&this.root_path).unwrap();
|
let project_relative = this.project_path.strip_prefix(&this.root_path).unwrap();
|
||||||
|
@ -182,13 +180,13 @@ impl ProjectVc {
|
||||||
.strip_prefix(MAIN_SEPARATOR)
|
.strip_prefix(MAIN_SEPARATOR)
|
||||||
.unwrap_or(project_relative)
|
.unwrap_or(project_relative)
|
||||||
.replace(MAIN_SEPARATOR, "/");
|
.replace(MAIN_SEPARATOR, "/");
|
||||||
Ok(root.join(&project_relative))
|
Ok(root.join(project_relative))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 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();
|
let next_router_root = next_router_fs.root();
|
||||||
Ok(find_pages_structure(
|
Ok(find_pages_structure(
|
||||||
self.project_path(),
|
self.project_path(),
|
||||||
|
@ -198,30 +196,31 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn env(self) -> ProcessEnvVc {
|
fn env(self: Vc<Self>) -> Vc<Box<dyn ProcessEnv>> {
|
||||||
load_env(self.project_path())
|
load_env(self.project_path())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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)
|
Ok(self.await?.next_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn execution_context(self) -> ExecutionContextVc {
|
fn execution_context(self: Vc<Self>) -> Vc<ExecutionContext> {
|
||||||
let node_root = self.node_root();
|
let node_root = self.node_root();
|
||||||
|
|
||||||
let node_execution_chunking_context = DevChunkingContextVc::builder(
|
let node_execution_chunking_context = Vc::upcast(
|
||||||
self.project_path(),
|
DevChunkingContext::builder(
|
||||||
node_root,
|
self.project_path(),
|
||||||
node_root.join("chunks"),
|
node_root,
|
||||||
node_root.join("assets"),
|
node_root.join("chunks".to_string()),
|
||||||
node_build_environment(),
|
node_root.join("assets".to_string()),
|
||||||
)
|
node_build_environment(),
|
||||||
.build()
|
)
|
||||||
.into();
|
.build(),
|
||||||
|
);
|
||||||
|
|
||||||
ExecutionContextVc::new(
|
ExecutionContext::new(
|
||||||
self.project_path(),
|
self.project_path(),
|
||||||
node_execution_chunking_context,
|
node_execution_chunking_context,
|
||||||
self.env(),
|
self.env(),
|
||||||
|
@ -229,40 +228,40 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
let this = self.await?;
|
||||||
Ok(get_client_compile_time_info(
|
Ok(get_client_compile_time_info(
|
||||||
this.mode,
|
this.mode,
|
||||||
&this.browserslist_query,
|
this.browserslist_query.clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
let this = self.await?;
|
||||||
Ok(get_server_compile_time_info(
|
Ok(get_server_compile_time_info(
|
||||||
this.mode,
|
this.mode,
|
||||||
self.env(),
|
self.env(),
|
||||||
// TODO(alexkirsz) Fill this out.
|
// TODO(alexkirsz) Fill this out.
|
||||||
ServerAddrVc::empty(),
|
ServerAddr::empty(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 {
|
Ok(if let Some(pages) = self.pages_structure().await?.pages {
|
||||||
pages.project_path()
|
pages.project_path()
|
||||||
} else {
|
} else {
|
||||||
self.project_path().join("pages")
|
self.project_path().join("pages".to_string())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn pages_transitions(self) -> TransitionsByNameVc {
|
fn pages_transitions(self: Vc<Self>) -> Vc<TransitionsByName> {
|
||||||
TransitionsByNameVc::cell(
|
Vc::cell(
|
||||||
[(
|
[(
|
||||||
"next-dynamic".to_string(),
|
"next-dynamic".to_string(),
|
||||||
NextDynamicTransitionVc::new(self.pages_client_transition()).into(),
|
Vc::upcast(NextDynamicTransition::new(self.pages_client_transition())),
|
||||||
)]
|
)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
@ -270,8 +269,8 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn pages_client_transition(self) -> ContextTransitionVc {
|
fn pages_client_transition(self: Vc<Self>) -> Vc<ContextTransition> {
|
||||||
ContextTransitionVc::new(
|
ContextTransition::new(
|
||||||
self.client_compile_time_info(),
|
self.client_compile_time_info(),
|
||||||
self.pages_client_module_options_context(),
|
self.pages_client_module_options_context(),
|
||||||
self.pages_client_resolve_options_context(),
|
self.pages_client_resolve_options_context(),
|
||||||
|
@ -279,7 +278,9 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
let this = self.await?;
|
||||||
Ok(get_client_module_options_context(
|
Ok(get_client_module_options_context(
|
||||||
self.project_path(),
|
self.project_path(),
|
||||||
|
@ -294,7 +295,9 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
let this = self.await?;
|
||||||
Ok(get_client_resolve_options_context(
|
Ok(get_client_resolve_options_context(
|
||||||
self.project_path(),
|
self.project_path(),
|
||||||
|
@ -308,40 +311,37 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) fn pages_client_module_context(self) -> AssetContextVc {
|
pub(super) fn pages_client_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
||||||
ModuleAssetContextVc::new(
|
Vc::upcast(ModuleAssetContext::new(
|
||||||
self.pages_transitions(),
|
self.pages_transitions(),
|
||||||
self.client_compile_time_info(),
|
self.client_compile_time_info(),
|
||||||
self.pages_client_module_options_context(),
|
self.pages_client_module_options_context(),
|
||||||
self.pages_client_resolve_options_context(),
|
self.pages_client_resolve_options_context(),
|
||||||
)
|
))
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) fn pages_ssr_module_context(self) -> AssetContextVc {
|
pub(super) fn pages_ssr_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
||||||
ModuleAssetContextVc::new(
|
Vc::upcast(ModuleAssetContext::new(
|
||||||
self.pages_transitions(),
|
self.pages_transitions(),
|
||||||
self.server_compile_time_info(),
|
self.server_compile_time_info(),
|
||||||
self.pages_ssr_module_options_context(),
|
self.pages_ssr_module_options_context(),
|
||||||
self.pages_ssr_resolve_options_context(),
|
self.pages_ssr_resolve_options_context(),
|
||||||
)
|
))
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) fn pages_ssr_data_module_context(self) -> AssetContextVc {
|
pub(super) fn pages_ssr_data_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
||||||
ModuleAssetContextVc::new(
|
Vc::upcast(ModuleAssetContext::new(
|
||||||
self.pages_transitions(),
|
self.pages_transitions(),
|
||||||
self.server_compile_time_info(),
|
self.server_compile_time_info(),
|
||||||
self.pages_ssr_data_module_options_context(),
|
self.pages_ssr_data_module_options_context(),
|
||||||
self.pages_ssr_resolve_options_context(),
|
self.pages_ssr_resolve_options_context(),
|
||||||
)
|
))
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
let this = self.await?;
|
||||||
Ok(get_server_module_options_context(
|
Ok(get_server_module_options_context(
|
||||||
self.project_path(),
|
self.project_path(),
|
||||||
|
@ -355,7 +355,9 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
let this = self.await?;
|
||||||
Ok(get_server_module_options_context(
|
Ok(get_server_module_options_context(
|
||||||
self.project_path(),
|
self.project_path(),
|
||||||
|
@ -369,7 +371,9 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
let this = self.await?;
|
||||||
Ok(get_server_resolve_options_context(
|
Ok(get_server_resolve_options_context(
|
||||||
self.project_path(),
|
self.project_path(),
|
||||||
|
@ -383,7 +387,9 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let client_runtime_entries = get_client_runtime_entries(
|
let client_runtime_entries = get_client_runtime_entries(
|
||||||
self.project_path(),
|
self.project_path(),
|
||||||
|
@ -399,7 +405,7 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let ssr_runtime_entries = get_server_runtime_entries(
|
let ssr_runtime_entries = get_server_runtime_entries(
|
||||||
self.project_path(),
|
self.project_path(),
|
||||||
|
@ -414,7 +420,9 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
let this = self.await?;
|
||||||
Ok(get_client_chunking_context(
|
Ok(get_client_chunking_context(
|
||||||
self.project_path(),
|
self.project_path(),
|
||||||
|
@ -425,7 +433,7 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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(
|
get_server_chunking_context(
|
||||||
self.project_path(),
|
self.project_path(),
|
||||||
self.node_root(),
|
self.node_root(),
|
||||||
|
@ -435,25 +443,29 @@ impl ProjectVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) async fn ssr_chunking_context(self) -> Result<BuildChunkingContextVc> {
|
pub(super) async fn ssr_chunking_context(self: Vc<Self>) -> Result<Vc<BuildChunkingContext>> {
|
||||||
let ssr_chunking_context = self.server_chunking_context().with_layer("ssr");
|
let ssr_chunking_context = self.server_chunking_context().with_layer("ssr".to_string());
|
||||||
BuildChunkingContextVc::resolve_from(ssr_chunking_context)
|
Vc::try_resolve_downcast_type::<BuildChunkingContext>(ssr_chunking_context)
|
||||||
.await?
|
.await?
|
||||||
.context("with_layer should not change the type of the chunking context")
|
.context("with_layer should not change the type of the chunking context")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) async fn ssr_data_chunking_context(self) -> Result<BuildChunkingContextVc> {
|
pub(super) async fn ssr_data_chunking_context(
|
||||||
let ssr_chunking_context = self.server_chunking_context().with_layer("ssr data");
|
self: Vc<Self>,
|
||||||
BuildChunkingContextVc::resolve_from(ssr_chunking_context)
|
) -> 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?
|
.await?
|
||||||
.context("with_layer should not change the type of the chunking context")
|
.context("with_layer should not change the type of the chunking context")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) async fn rsc_chunking_context(self) -> Result<BuildChunkingContextVc> {
|
pub(super) async fn rsc_chunking_context(self: Vc<Self>) -> Result<Vc<BuildChunkingContext>> {
|
||||||
let rsc_chunking_context = self.server_chunking_context().with_layer("rsc");
|
let rsc_chunking_context = self.server_chunking_context().with_layer("rsc".to_string());
|
||||||
BuildChunkingContextVc::resolve_from(rsc_chunking_context)
|
Vc::try_resolve_downcast_type::<BuildChunkingContext>(rsc_chunking_context)
|
||||||
.await?
|
.await?
|
||||||
.context("with_layer should not change the type of the chunking context")
|
.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
|
/// Scans the app/pages directories for entry points files (matching the
|
||||||
/// provided page_extensions).
|
/// provided page_extensions).
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let mut routes = IndexMap::new();
|
let mut routes = IndexMap::new();
|
||||||
if let Some(app_dir) = *find_app_dir(self.project_path()).await? {
|
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
|
/// Emits opaque HMR events whenever a change is detected in the chunk group
|
||||||
/// internally known as `identifier`.
|
/// internally known as `identifier`.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn hmr_events(self, _identifier: String, _sender: TransientValue<()>) -> NothingVc {
|
pub fn hmr_events(self: Vc<Self>, _identifier: String, _sender: TransientValue<()>) -> Vc<()> {
|
||||||
NothingVc::new()
|
unit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn project_fs(project_dir: &str, watching: bool) -> Result<FileSystemVc> {
|
async fn project_fs(project_dir: String, watching: bool) -> Result<Vc<Box<dyn FileSystem>>> {
|
||||||
let disk_fs =
|
let disk_fs = DiskFileSystem::new(PROJECT_FILESYSTEM_NAME.to_string(), project_dir.to_string());
|
||||||
DiskFileSystemVc::new(PROJECT_FILESYSTEM_NAME.to_string(), project_dir.to_string());
|
|
||||||
if watching {
|
if watching {
|
||||||
disk_fs.await?.start_watching_with_invalidation_reason()?;
|
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 indexmap::IndexMap;
|
||||||
use turbo_tasks::CompletionVc;
|
use turbo_tasks::{Completion, Vc};
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum Route {
|
pub enum Route {
|
||||||
Page {
|
Page {
|
||||||
html_endpoint: EndpointVc,
|
html_endpoint: Vc<Box<dyn Endpoint>>,
|
||||||
data_endpoint: EndpointVc,
|
data_endpoint: Vc<Box<dyn Endpoint>>,
|
||||||
},
|
},
|
||||||
PageApi {
|
PageApi {
|
||||||
endpoint: EndpointVc,
|
endpoint: Vc<Box<dyn Endpoint>>,
|
||||||
},
|
},
|
||||||
AppPage {
|
AppPage {
|
||||||
html_endpoint: EndpointVc,
|
html_endpoint: Vc<Box<dyn Endpoint>>,
|
||||||
rsc_endpoint: EndpointVc,
|
rsc_endpoint: Vc<Box<dyn Endpoint>>,
|
||||||
},
|
},
|
||||||
AppRoute {
|
AppRoute {
|
||||||
endpoint: EndpointVc,
|
endpoint: Vc<Box<dyn Endpoint>>,
|
||||||
},
|
},
|
||||||
Conflict,
|
Conflict,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_trait]
|
#[turbo_tasks::value_trait]
|
||||||
pub trait Endpoint {
|
pub trait Endpoint {
|
||||||
fn write_to_disk(&self) -> WrittenEndpointVc;
|
fn write_to_disk(self: Vc<Self>) -> Vc<WrittenEndpoint>;
|
||||||
fn changed(&self) -> CompletionVc;
|
fn changed(self: Vc<Self>) -> Vc<Completion>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
#![feature(arbitrary_self_types)]
|
||||||
|
#![feature(async_fn_in_trait)]
|
||||||
|
|
||||||
use turbopack_binding::turbo::{
|
use turbopack_binding::turbo::{
|
||||||
tasks::{run_once, TransientInstance, TurboTasks},
|
tasks::{run_once, TransientInstance, TurboTasks},
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#![feature(arbitrary_self_types)]
|
||||||
|
#![feature(async_fn_in_trait)]
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
|
@ -2,15 +2,18 @@ use std::collections::HashSet;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use next_core::{self, next_client_reference::ClientReferenceType};
|
use next_core::{
|
||||||
use turbo_tasks::TryJoinIterExt;
|
next_client_reference::ClientReferenceType,
|
||||||
|
{self},
|
||||||
|
};
|
||||||
|
use turbo_tasks::{TryJoinIterExt, Vc};
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
build::BuildChunkingContextVc,
|
build::BuildChunkingContext,
|
||||||
core::{
|
core::{
|
||||||
chunk::{ChunkableModule, ChunkingContext},
|
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
|
/// Computes all client references chunks, and adds them to the relevant
|
||||||
|
@ -20,9 +23,9 @@ use turbopack_binding::turbopack::{
|
||||||
/// type needs to load.
|
/// type needs to load.
|
||||||
pub async fn compute_app_client_references_chunks(
|
pub async fn compute_app_client_references_chunks(
|
||||||
app_client_reference_types: &HashSet<ClientReferenceType>,
|
app_client_reference_types: &HashSet<ClientReferenceType>,
|
||||||
client_chunking_context: EcmascriptChunkingContextVc,
|
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
ssr_chunking_context: BuildChunkingContextVc,
|
ssr_chunking_context: Vc<BuildChunkingContext>,
|
||||||
all_chunks: &mut Vec<OutputAssetVc>,
|
all_chunks: &mut Vec<Vc<Box<dyn OutputAsset>>>,
|
||||||
) -> Result<IndexMap<ClientReferenceType, ClientReferenceChunks>> {
|
) -> Result<IndexMap<ClientReferenceType, ClientReferenceChunks>> {
|
||||||
let app_client_references_chunks: IndexMap<_, _> = app_client_reference_types
|
let app_client_references_chunks: IndexMap<_, _> = app_client_reference_types
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -34,10 +37,10 @@ pub async fn compute_app_client_references_chunks(
|
||||||
let ecmascript_client_reference_ref = ecmascript_client_reference.await?;
|
let ecmascript_client_reference_ref = ecmascript_client_reference.await?;
|
||||||
let client_entry_chunk = ecmascript_client_reference_ref
|
let client_entry_chunk = ecmascript_client_reference_ref
|
||||||
.client_module
|
.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
|
let ssr_entry_chunk = ecmascript_client_reference_ref
|
||||||
.ssr_module
|
.ssr_module
|
||||||
.as_root_chunk(ssr_chunking_context.into());
|
.as_root_chunk(Vc::upcast(ssr_chunking_context));
|
||||||
ClientReferenceChunks {
|
ClientReferenceChunks {
|
||||||
client_chunks: client_chunking_context.chunk_group(client_entry_chunk),
|
client_chunks: client_chunking_context.chunk_group(client_entry_chunk),
|
||||||
ssr_chunks: ssr_chunking_context.chunk_group(ssr_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 css_client_reference_ref = css_client_reference.await?;
|
||||||
let client_entry_chunk = css_client_reference_ref
|
let client_entry_chunk = css_client_reference_ref
|
||||||
.client_module
|
.client_module
|
||||||
.as_root_chunk(client_chunking_context.into());
|
.as_root_chunk(Vc::upcast(client_chunking_context));
|
||||||
ClientReferenceChunks {
|
ClientReferenceChunks {
|
||||||
client_chunks: client_chunking_context.chunk_group(client_entry_chunk),
|
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.
|
/// Contains the chunks corresponding to a client reference.
|
||||||
pub struct ClientReferenceChunks {
|
pub struct ClientReferenceChunks {
|
||||||
/// Chunks to be loaded on the client.
|
/// 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.
|
/// 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,
|
get_client_runtime_entries, ClientContextType,
|
||||||
},
|
},
|
||||||
next_client_reference::{
|
next_client_reference::{
|
||||||
ClientReference, ClientReferenceType, NextEcmascriptClientReferenceTransitionVc,
|
ClientReference, ClientReferenceType, NextEcmascriptClientReferenceTransition,
|
||||||
},
|
},
|
||||||
next_config::NextConfigVc,
|
next_config::NextConfig,
|
||||||
next_dynamic::NextDynamicTransitionVc,
|
next_dynamic::NextDynamicTransition,
|
||||||
next_server::{
|
next_server::{
|
||||||
get_server_module_options_context, get_server_resolve_options_context,
|
get_server_module_options_context, get_server_resolve_options_context,
|
||||||
get_server_runtime_entries, ServerContextType,
|
get_server_runtime_entries, ServerContextType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value, ValueToString};
|
use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{
|
turbo::{
|
||||||
tasks_env::{CustomProcessEnvVc, ProcessEnvVc},
|
tasks_env::{CustomProcessEnv, ProcessEnv},
|
||||||
tasks_fs::{File, FileSystemPath, FileSystemPathVc},
|
tasks_fs::{File, FileSystemPath},
|
||||||
},
|
},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
build::BuildChunkingContextVc,
|
build::BuildChunkingContext,
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
chunk::{
|
chunk::{
|
||||||
availability_info::AvailabilityInfo, ChunkingContext, EvaluatableAssetsVc,
|
availability_info::AvailabilityInfo, ChunkingContext, EvaluatableAssets,
|
||||||
ModuleId as TurbopackModuleId,
|
ModuleId as TurbopackModuleId,
|
||||||
},
|
},
|
||||||
compile_time_info::CompileTimeInfoVc,
|
compile_time_info::CompileTimeInfo,
|
||||||
file_source::FileSourceVc,
|
file_source::FileSource,
|
||||||
output::{OutputAssetVc, OutputAssetsVc},
|
output::{OutputAsset, OutputAssets},
|
||||||
raw_output::RawOutputVc,
|
raw_output::RawOutput,
|
||||||
virtual_source::VirtualSourceVc,
|
virtual_source::VirtualSource,
|
||||||
},
|
},
|
||||||
ecmascript::{
|
ecmascript::{
|
||||||
chunk::{
|
chunk::{
|
||||||
EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkPlaceablesVc,
|
EcmascriptChunk, EcmascriptChunkItemExt, EcmascriptChunkPlaceable,
|
||||||
EcmascriptChunkVc, EcmascriptChunkingContextVc,
|
EcmascriptChunkingContext,
|
||||||
},
|
},
|
||||||
utils::StringifyJs,
|
utils::StringifyJs,
|
||||||
},
|
},
|
||||||
node::execution_context::ExecutionContextVc,
|
node::execution_context::ExecutionContext,
|
||||||
turbopack::{
|
turbopack::{transition::ContextTransition, ModuleAssetContext},
|
||||||
transition::{ContextTransitionVc, TransitionsByNameVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,38 +70,38 @@ pub struct AppEntry {
|
||||||
/// the pathname to refer to this entry.
|
/// the pathname to refer to this entry.
|
||||||
pub original_name: String,
|
pub original_name: String,
|
||||||
/// The RSC module asset for the route or page.
|
/// The RSC module asset for the route or page.
|
||||||
pub rsc_entry: EcmascriptChunkPlaceableVc,
|
pub rsc_entry: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub struct AppEntries {
|
pub struct AppEntries {
|
||||||
/// All app entries.
|
/// All app entries.
|
||||||
pub entries: Vec<AppEntryVc>,
|
pub entries: Vec<Vc<AppEntry>>,
|
||||||
/// The RSC runtime entries that should be evaluated before any app entry
|
/// The RSC runtime entries that should be evaluated before any app entry
|
||||||
/// module when server rendering.
|
/// 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
|
/// The client runtime entries that should be evaluated before any app entry
|
||||||
/// module when client rendering.
|
/// 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.
|
/// Computes all app entries found under the given project root.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_app_entries(
|
pub async fn get_app_entries(
|
||||||
project_root: FileSystemPathVc,
|
project_root: Vc<FileSystemPath>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
env: ProcessEnvVc,
|
env: Vc<Box<dyn ProcessEnv>>,
|
||||||
client_compile_time_info: CompileTimeInfoVc,
|
client_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
server_compile_time_info: CompileTimeInfoVc,
|
server_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
) -> Result<AppEntriesVc> {
|
) -> Result<Vc<AppEntries>> {
|
||||||
let app_dir = find_app_dir_if_enabled(project_root, next_config);
|
let app_dir = find_app_dir_if_enabled(project_root, next_config);
|
||||||
|
|
||||||
let Some(&app_dir) = app_dir.await?.as_ref() else {
|
let Some(&app_dir) = app_dir.await?.as_ref() else {
|
||||||
return Ok(AppEntriesVc::cell(AppEntries {
|
return Ok(AppEntries::cell(AppEntries {
|
||||||
entries: vec![],
|
entries: vec![],
|
||||||
rsc_runtime_entries: EvaluatableAssetsVc::empty(),
|
rsc_runtime_entries: EvaluatableAssets::empty(),
|
||||||
client_runtime_entries: EvaluatableAssetsVc::empty(),
|
client_runtime_entries: EvaluatableAssets::empty(),
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -124,7 +121,7 @@ pub async fn get_app_entries(
|
||||||
// app_source?
|
// app_source?
|
||||||
let runtime_entries = get_server_runtime_entries(project_root, env, rsc_ty, mode, next_config);
|
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 });
|
let ssr_ty: Value<ServerContextType> = Value::new(ServerContextType::AppSSR { app_dir });
|
||||||
|
|
||||||
|
@ -147,7 +144,7 @@ pub async fn get_app_entries(
|
||||||
execution_context,
|
execution_context,
|
||||||
);
|
);
|
||||||
|
|
||||||
let client_transition = ContextTransitionVc::new(
|
let client_transition = ContextTransition::new(
|
||||||
client_compile_time_info,
|
client_compile_time_info,
|
||||||
client_module_options_context,
|
client_module_options_context,
|
||||||
client_resolve_options_context,
|
client_resolve_options_context,
|
||||||
|
@ -169,7 +166,7 @@ pub async fn get_app_entries(
|
||||||
next_config,
|
next_config,
|
||||||
);
|
);
|
||||||
|
|
||||||
let ssr_transition = ContextTransitionVc::new(
|
let ssr_transition = ContextTransition::new(
|
||||||
server_compile_time_info,
|
server_compile_time_info,
|
||||||
ssr_module_options_context,
|
ssr_module_options_context,
|
||||||
ssr_resolve_options_context,
|
ssr_resolve_options_context,
|
||||||
|
@ -179,19 +176,22 @@ pub async fn get_app_entries(
|
||||||
|
|
||||||
transitions.insert(
|
transitions.insert(
|
||||||
ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string(),
|
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 });
|
let client_ty = Value::new(ClientContextType::App { app_dir });
|
||||||
transitions.insert(
|
transitions.insert(
|
||||||
"next-dynamic".to_string(),
|
"next-dynamic".to_string(),
|
||||||
NextDynamicTransitionVc::new(client_transition).into(),
|
Vc::upcast(NextDynamicTransition::new(client_transition)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let rsc_ty = Value::new(ServerContextType::AppRSC {
|
let rsc_ty = Value::new(ServerContextType::AppRSC {
|
||||||
app_dir,
|
app_dir,
|
||||||
client_transition: Some(client_transition.into()),
|
client_transition: Some(Vc::upcast(client_transition)),
|
||||||
ecmascript_client_reference_transition_name: Some(StringVc::cell(
|
ecmascript_client_reference_transition_name: Some(Vc::cell(
|
||||||
ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string(),
|
ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string(),
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
|
@ -211,8 +211,8 @@ pub async fn get_app_entries(
|
||||||
execution_context,
|
execution_context,
|
||||||
);
|
);
|
||||||
|
|
||||||
let rsc_context = ModuleAssetContextVc::new(
|
let rsc_context = ModuleAssetContext::new(
|
||||||
TransitionsByNameVc::cell(transitions),
|
Vc::cell(transitions),
|
||||||
server_compile_time_info,
|
server_compile_time_info,
|
||||||
rsc_module_options_context,
|
rsc_module_options_context,
|
||||||
rsc_resolve_options_context,
|
rsc_resolve_options_context,
|
||||||
|
@ -230,7 +230,7 @@ pub async fn get_app_entries(
|
||||||
Entrypoint::AppRoute { path } => {
|
Entrypoint::AppRoute { path } => {
|
||||||
get_app_route_entry(
|
get_app_route_entry(
|
||||||
rsc_context,
|
rsc_context,
|
||||||
FileSourceVc::new(*path).into(),
|
Vc::upcast(FileSource::new(*path)),
|
||||||
pathname,
|
pathname,
|
||||||
project_root,
|
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?);
|
entries.push(get_app_route_favicon_entry(rsc_context, favicon, project_root).await?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let client_context = ModuleAssetContextVc::new(
|
let client_context = ModuleAssetContext::new(
|
||||||
TransitionsByNameVc::cell(Default::default()),
|
Vc::cell(Default::default()),
|
||||||
client_compile_time_info,
|
client_compile_time_info,
|
||||||
client_module_options_context,
|
client_module_options_context,
|
||||||
client_resolve_options_context,
|
client_resolve_options_context,
|
||||||
|
@ -264,10 +264,10 @@ pub async fn get_app_entries(
|
||||||
execution_context,
|
execution_context,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(AppEntriesVc::cell(AppEntries {
|
Ok(AppEntries::cell(AppEntries {
|
||||||
entries,
|
entries,
|
||||||
rsc_runtime_entries: runtime_entries.resolve_entries(rsc_context.into()),
|
rsc_runtime_entries: runtime_entries.resolve_entries(Vc::upcast(rsc_context)),
|
||||||
client_runtime_entries: client_runtime_entries.resolve_entries(client_context.into()),
|
client_runtime_entries: client_runtime_entries.resolve_entries(Vc::upcast(client_context)),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,18 +276,18 @@ pub async fn get_app_entries(
|
||||||
/// manifests.
|
/// manifests.
|
||||||
pub async fn compute_app_entries_chunks(
|
pub async fn compute_app_entries_chunks(
|
||||||
app_entries: &AppEntries,
|
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>,
|
app_client_references_chunks: &IndexMap<ClientReferenceType, ClientReferenceChunks>,
|
||||||
rsc_chunking_context: BuildChunkingContextVc,
|
rsc_chunking_context: Vc<BuildChunkingContext>,
|
||||||
client_chunking_context: EcmascriptChunkingContextVc,
|
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
ssr_chunking_context: EcmascriptChunkingContextVc,
|
ssr_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
node_root: FileSystemPathVc,
|
node_root: Vc<FileSystemPath>,
|
||||||
client_relative_path: &FileSystemPath,
|
client_relative_path: &FileSystemPath,
|
||||||
app_paths_manifest_dir_path: &FileSystemPath,
|
app_paths_manifest_dir_path: &FileSystemPath,
|
||||||
app_build_manifest: &mut AppBuildManifest,
|
app_build_manifest: &mut AppBuildManifest,
|
||||||
build_manifest: &mut BuildManifest,
|
build_manifest: &mut BuildManifest,
|
||||||
app_paths_manifest: &mut AppPathsManifest,
|
app_paths_manifest: &mut AppPathsManifest,
|
||||||
all_chunks: &mut Vec<OutputAssetVc>,
|
all_chunks: &mut Vec<Vc<Box<dyn OutputAsset>>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let node_root_ref = node_root.await?;
|
let node_root_ref = node_root.await?;
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ pub async fn compute_app_entries_chunks(
|
||||||
all_chunks.push(chunk);
|
all_chunks.push(chunk);
|
||||||
|
|
||||||
let chunk_path = chunk.ident().path().await?;
|
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) {
|
if let Some(chunk_path) = client_relative_path.get_path_to(&chunk_path) {
|
||||||
app_shared_client_chunks_paths.push(chunk_path.to_string());
|
app_shared_client_chunks_paths.push(chunk_path.to_string());
|
||||||
build_manifest.root_main_files.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 = app_entry.await?;
|
||||||
|
|
||||||
let app_entry_client_references = app_client_references_by_entry
|
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");
|
.expect("app entry should have a corresponding client references list");
|
||||||
|
|
||||||
let rsc_chunk = rsc_chunking_context.entry_chunk(
|
let rsc_chunk = rsc_chunking_context.entry_chunk(
|
||||||
node_root.join(&format!(
|
node_root.join(format!(
|
||||||
"server/app/{original_name}.js",
|
"server/app/{original_name}.js",
|
||||||
original_name = app_entry.original_name
|
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() {
|
if let Some(server_component) = app_client_reference.server_component() {
|
||||||
let server_component_name = server_component
|
let server_component_name = server_component
|
||||||
.server_path()
|
.server_path()
|
||||||
.with_extension("")
|
.with_extension("".to_string())
|
||||||
.to_string()
|
.to_string()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -414,7 +414,7 @@ pub async fn compute_app_entries_chunks(
|
||||||
client_chunks_paths
|
client_chunks_paths
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|chunk_path| {
|
.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)
|
client_relative_path.get_path_to(chunk_path)
|
||||||
} else {
|
} else {
|
||||||
None
|
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_json = serde_json::to_string(&entry_manifest).unwrap();
|
||||||
let client_reference_manifest_source = VirtualSourceVc::new(
|
let client_reference_manifest_source = VirtualSource::new(
|
||||||
node_root.join(&format!(
|
node_root.join(format!(
|
||||||
"server/app/{original_name}_client-reference-manifest.js",
|
"server/app/{original_name}_client-reference-manifest.js",
|
||||||
original_name = app_entry.original_name
|
original_name = app_entry.original_name
|
||||||
)),
|
)),
|
||||||
File::from(formatdoc! {
|
AssetContent::file(
|
||||||
r#"
|
File::from(formatdoc! {
|
||||||
|
r#"
|
||||||
globalThis.__RSC_MANIFEST = globalThis.__RSC_MANIFEST || {{}};
|
globalThis.__RSC_MANIFEST = globalThis.__RSC_MANIFEST || {{}};
|
||||||
globalThis.__RSC_MANIFEST[{original_name}] = {manifest}
|
globalThis.__RSC_MANIFEST[{original_name}] = {manifest}
|
||||||
"#,
|
"#,
|
||||||
original_name = StringifyJs(&app_entry.original_name),
|
original_name = StringifyJs(&app_entry.original_name),
|
||||||
manifest = StringifyJs(&client_reference_manifest_json)
|
manifest = StringifyJs(&client_reference_manifest_json)
|
||||||
})
|
})
|
||||||
.into(),
|
.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(())
|
Ok(())
|
||||||
|
@ -529,23 +533,25 @@ pub async fn compute_app_entries_chunks(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_app_shared_client_chunk(
|
pub async fn get_app_shared_client_chunk(
|
||||||
app_client_runtime_entries: EvaluatableAssetsVc,
|
app_client_runtime_entries: Vc<EvaluatableAssets>,
|
||||||
client_chunking_context: EcmascriptChunkingContextVc,
|
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
) -> Result<EcmascriptChunkVc> {
|
) -> Result<Vc<EcmascriptChunk>> {
|
||||||
let client_runtime_entries: Vec<_> = app_client_runtime_entries
|
let client_runtime_entries: Vec<_> = app_client_runtime_entries
|
||||||
.await?
|
.await?
|
||||||
.iter()
|
.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()
|
.try_join()
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(EcmascriptChunkVc::new_normalized(
|
Ok(EcmascriptChunk::new_normalized(
|
||||||
client_chunking_context,
|
client_chunking_context,
|
||||||
// TODO(alexkirsz) Should this accept Evaluatable instead?
|
// TODO(alexkirsz) Should this accept Evaluatable instead?
|
||||||
EcmascriptChunkPlaceablesVc::cell(client_runtime_entries),
|
Vc::cell(client_runtime_entries),
|
||||||
None,
|
None,
|
||||||
Value::new(AvailabilityInfo::Untracked),
|
Value::new(AvailabilityInfo::Untracked),
|
||||||
))
|
))
|
||||||
|
@ -553,18 +559,20 @@ pub async fn get_app_shared_client_chunk(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_app_client_shared_chunks(
|
pub async fn get_app_client_shared_chunks(
|
||||||
app_client_runtime_entries: EvaluatableAssetsVc,
|
app_client_runtime_entries: Vc<EvaluatableAssets>,
|
||||||
client_chunking_context: EcmascriptChunkingContextVc,
|
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
) -> Result<OutputAssetsVc> {
|
) -> Result<Vc<OutputAssets>> {
|
||||||
if app_client_runtime_entries.await?.is_empty() {
|
if app_client_runtime_entries.await?.is_empty() {
|
||||||
return Ok(OutputAssetsVc::empty());
|
return Ok(OutputAssets::empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
let app_client_shared_chunk =
|
let app_client_shared_chunk =
|
||||||
get_app_shared_client_chunk(app_client_runtime_entries, client_chunking_context);
|
get_app_shared_client_chunk(app_client_runtime_entries, client_chunking_context);
|
||||||
|
|
||||||
let app_client_shared_chunks = client_chunking_context
|
let app_client_shared_chunks = client_chunking_context.evaluated_chunk_group(
|
||||||
.evaluated_chunk_group(app_client_shared_chunk.into(), app_client_runtime_entries);
|
Vc::upcast(app_client_shared_chunk),
|
||||||
|
app_client_runtime_entries,
|
||||||
|
);
|
||||||
|
|
||||||
Ok(app_client_shared_chunks)
|
Ok(app_client_shared_chunks)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,37 +3,36 @@ use std::io::Write;
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use indoc::writedoc;
|
use indoc::writedoc;
|
||||||
use next_core::{
|
use next_core::{
|
||||||
app_structure::LoaderTreeVc,
|
app_structure::LoaderTree,
|
||||||
loader_tree::{LoaderTreeModule, ServerComponentTransition},
|
loader_tree::{LoaderTreeModule, ServerComponentTransition},
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
next_server_component::NextServerComponentTransitionVc,
|
next_server_component::NextServerComponentTransition,
|
||||||
UnsupportedDynamicMetadataIssue,
|
UnsupportedDynamicMetadataIssue,
|
||||||
};
|
};
|
||||||
use turbo_tasks::{TryJoinIterExt, Value, ValueToString};
|
use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPathVc},
|
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPath},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
context::AssetContext,
|
asset::AssetContent, context::AssetContext, issue::IssueExt,
|
||||||
reference_type::{InnerAssetsVc, ReferenceType},
|
reference_type::ReferenceType, virtual_source::VirtualSource,
|
||||||
virtual_source::VirtualSourceVc,
|
|
||||||
},
|
},
|
||||||
ecmascript::{chunk::EcmascriptChunkPlaceableVc, utils::StringifyJs},
|
ecmascript::{chunk::EcmascriptChunkPlaceable, utils::StringifyJs},
|
||||||
turbopack::ModuleAssetContextVc,
|
turbopack::ModuleAssetContext,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::app_entries::{AppEntry, AppEntryVc};
|
use super::app_entries::AppEntry;
|
||||||
|
|
||||||
/// Computes the entry for a Next.js app page.
|
/// Computes the entry for a Next.js app page.
|
||||||
pub(super) async fn get_app_page_entry(
|
pub(super) async fn get_app_page_entry(
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
loader_tree: LoaderTreeVc,
|
loader_tree: Vc<LoaderTree>,
|
||||||
app_dir: FileSystemPathVc,
|
app_dir: Vc<FileSystemPath>,
|
||||||
pathname: &str,
|
pathname: &str,
|
||||||
project_root: FileSystemPathVc,
|
project_root: Vc<FileSystemPath>,
|
||||||
) -> Result<AppEntryVc> {
|
) -> Result<Vc<AppEntry>> {
|
||||||
let server_component_transition = NextServerComponentTransitionVc::new().into();
|
let server_component_transition = Vc::upcast(NextServerComponentTransition::new());
|
||||||
|
|
||||||
let loader_tree = LoaderTreeModule::build(
|
let loader_tree = LoaderTreeModule::build(
|
||||||
loader_tree,
|
loader_tree,
|
||||||
|
@ -57,7 +56,6 @@ pub(super) async fn get_app_page_entry(
|
||||||
files: unsupported_metadata,
|
files: unsupported_metadata,
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
.as_issue()
|
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,14 +93,16 @@ pub(super) async fn get_app_page_entry(
|
||||||
let file = File::from(result.build());
|
let file = File::from(result.build());
|
||||||
let source =
|
let source =
|
||||||
// TODO(alexkirsz) Figure out how to name this virtual asset.
|
// 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(
|
let rsc_entry = context.process(
|
||||||
source.into(),
|
Vc::upcast(source),
|
||||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(inner_assets))),
|
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");
|
bail!("expected an ECMAScript chunk placeable asset");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,31 +4,31 @@ use anyhow::{bail, Result};
|
||||||
use indexmap::indexmap;
|
use indexmap::indexmap;
|
||||||
use indoc::writedoc;
|
use indoc::writedoc;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use turbo_tasks::{Value, ValueToString};
|
use turbo_tasks::{Value, ValueToString, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPathVc},
|
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPath},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::Asset,
|
asset::{Asset, AssetContent},
|
||||||
context::AssetContext,
|
context::AssetContext,
|
||||||
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssetsVc, ReferenceType},
|
reference_type::{EcmaScriptModulesReferenceSubType, ReferenceType},
|
||||||
source::SourceVc,
|
source::Source,
|
||||||
virtual_source::VirtualSourceVc,
|
virtual_source::VirtualSource,
|
||||||
},
|
},
|
||||||
ecmascript::{chunk::EcmascriptChunkPlaceableVc, utils::StringifyJs},
|
ecmascript::{chunk::EcmascriptChunkPlaceable, utils::StringifyJs},
|
||||||
turbopack::ModuleAssetContextVc,
|
turbopack::ModuleAssetContext,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::app_entries::{AppEntry, AppEntryVc};
|
use super::app_entries::AppEntry;
|
||||||
|
|
||||||
/// Computes the entry for a Next.js app route.
|
/// Computes the entry for a Next.js app route.
|
||||||
pub(super) async fn get_app_route_entry(
|
pub(super) async fn get_app_route_entry(
|
||||||
rsc_context: ModuleAssetContextVc,
|
rsc_context: Vc<ModuleAssetContext>,
|
||||||
source: SourceVc,
|
source: Vc<Box<dyn Source>>,
|
||||||
pathname: &str,
|
pathname: &str,
|
||||||
project_root: FileSystemPathVc,
|
project_root: Vc<FileSystemPath>,
|
||||||
) -> Result<AppEntryVc> {
|
) -> Result<Vc<AppEntry>> {
|
||||||
let mut result = RopeBuilder::default();
|
let mut result = RopeBuilder::default();
|
||||||
|
|
||||||
let kind = "app-route";
|
let kind = "app-route";
|
||||||
|
@ -99,7 +99,10 @@ pub(super) async fn get_app_route_entry(
|
||||||
|
|
||||||
let file = File::from(result.build());
|
let file = File::from(result.build());
|
||||||
// TODO(alexkirsz) Figure out how to name this virtual asset.
|
// 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(
|
let entry = rsc_context.process(
|
||||||
source,
|
source,
|
||||||
|
@ -109,15 +112,17 @@ pub(super) async fn get_app_route_entry(
|
||||||
);
|
);
|
||||||
|
|
||||||
let inner_assets = indexmap! {
|
let inner_assets = indexmap! {
|
||||||
"ENTRY".to_string() => entry.into()
|
"ENTRY".to_string() => Vc::upcast(entry)
|
||||||
};
|
};
|
||||||
|
|
||||||
let rsc_entry = rsc_context.process(
|
let rsc_entry = rsc_context.process(
|
||||||
virtual_source.into(),
|
Vc::upcast(virtual_source),
|
||||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(inner_assets))),
|
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");
|
bail!("expected an ECMAScript chunk placeable asset");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,23 +4,24 @@ use anyhow::{bail, Result};
|
||||||
use base64::{display::Base64Display, engine::general_purpose::STANDARD};
|
use base64::{display::Base64Display, engine::general_purpose::STANDARD};
|
||||||
use indoc::writedoc;
|
use indoc::writedoc;
|
||||||
use next_core::app_structure::MetadataItem;
|
use next_core::app_structure::MetadataItem;
|
||||||
use turbo_tasks::ValueToString;
|
use turbo_tasks::{ValueToString, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileContent, FileSystemPathVc},
|
turbo::tasks_fs::{rope::RopeBuilder, File, FileContent, FileSystemPath},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::virtual_source::VirtualSourceVc, ecmascript::utils::StringifyJs,
|
core::{asset::AssetContent, virtual_source::VirtualSource},
|
||||||
turbopack::ModuleAssetContextVc,
|
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.
|
/// Computes the entry for a Next.js favicon file.
|
||||||
pub(super) async fn get_app_route_favicon_entry(
|
pub(super) async fn get_app_route_favicon_entry(
|
||||||
rsc_context: ModuleAssetContextVc,
|
rsc_context: Vc<ModuleAssetContext>,
|
||||||
favicon: MetadataItem,
|
favicon: MetadataItem,
|
||||||
project_root: FileSystemPathVc,
|
project_root: Vc<FileSystemPath>,
|
||||||
) -> Result<AppEntryVc> {
|
) -> Result<Vc<AppEntry>> {
|
||||||
let path = match favicon {
|
let path = match favicon {
|
||||||
// TODO(alexkirsz) Is there a difference here?
|
// TODO(alexkirsz) Is there a difference here?
|
||||||
MetadataItem::Static { path } => path,
|
MetadataItem::Static { path } => path,
|
||||||
|
@ -74,11 +75,11 @@ pub(super) async fn get_app_route_favicon_entry(
|
||||||
let file = File::from(code.build());
|
let file = File::from(code.build());
|
||||||
let source =
|
let source =
|
||||||
// TODO(alexkirsz) Figure out how to name this virtual 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(
|
get_app_route_entry(
|
||||||
rsc_context,
|
rsc_context,
|
||||||
source.into(),
|
Vc::upcast(source),
|
||||||
// TODO(alexkirsz) Get this from the metadata?
|
// TODO(alexkirsz) Get this from the metadata?
|
||||||
"/favicon.ico",
|
"/favicon.ico",
|
||||||
project_root,
|
project_root,
|
||||||
|
|
|
@ -7,42 +7,38 @@ use std::{
|
||||||
use anyhow::{anyhow, bail, Context, Result};
|
use anyhow::{anyhow, bail, Context, Result};
|
||||||
use dunce::canonicalize;
|
use dunce::canonicalize;
|
||||||
use next_core::{
|
use next_core::{
|
||||||
self,
|
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
next_client::{get_client_chunking_context, get_client_compile_time_info},
|
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_config::load_next_config,
|
||||||
next_dynamic::NextDynamicEntriesVc,
|
next_dynamic::NextDynamicEntries,
|
||||||
next_server::{get_server_chunking_context, get_server_compile_time_info},
|
next_server::{get_server_chunking_context, get_server_compile_time_info},
|
||||||
url_node::get_sorted_routes,
|
url_node::get_sorted_routes,
|
||||||
|
{self},
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{
|
||||||
graph::{AdjacencyMap, GraphTraversal},
|
graph::{AdjacencyMap, GraphTraversal},
|
||||||
CollectiblesSource, CompletionVc, CompletionsVc, RawVc, TransientInstance, TransientValue,
|
Completion, Completions, TransientInstance, TransientValue, TryJoinIterExt, Vc,
|
||||||
TryJoinIterExt,
|
|
||||||
};
|
};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::{
|
turbo::tasks_fs::{rebase, DiskFileSystem, FileContent, FileSystem, FileSystemPath},
|
||||||
rebase, DiskFileSystemVc, FileContent, FileSystem, FileSystemPath, FileSystemPathVc,
|
|
||||||
FileSystemVc,
|
|
||||||
},
|
|
||||||
turbopack::{
|
turbopack::{
|
||||||
build::BuildChunkingContextVc,
|
build::BuildChunkingContext,
|
||||||
cli_utils::issue::{ConsoleUiVc, LogOptions},
|
cli_utils::issue::{ConsoleUi, LogOptions},
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetVc, AssetsVc},
|
asset::{Asset, Assets},
|
||||||
chunk::ChunkingContext,
|
chunk::ChunkingContext,
|
||||||
environment::ServerAddrVc,
|
environment::ServerAddr,
|
||||||
issue::{IssueReporter, IssueReporterVc, IssueSeverity, IssueVc},
|
issue::{IssueContextExt, IssueReporter, IssueSeverity},
|
||||||
output::{OutputAssetVc, OutputAssetsVc},
|
output::{OutputAsset, OutputAssets},
|
||||||
reference::AssetReference,
|
reference::AssetReference,
|
||||||
virtual_fs::VirtualFileSystemVc,
|
virtual_fs::VirtualFileSystem,
|
||||||
},
|
},
|
||||||
dev::DevChunkingContextVc,
|
dev::DevChunkingContext,
|
||||||
ecmascript::utils::StringifyJs,
|
ecmascript::utils::StringifyJs,
|
||||||
env::dotenv::load_env,
|
env::dotenv::load_env,
|
||||||
node::execution_context::ExecutionContextVc,
|
node::execution_context::ExecutionContext,
|
||||||
turbopack::evaluate_context::node_build_environment,
|
turbopack::evaluate_context::node_build_environment,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -62,7 +58,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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
|
let project_root = options
|
||||||
.dir
|
.dir
|
||||||
.as_ref()
|
.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 \
|
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 {
|
let log_options = LogOptions {
|
||||||
project_dir: PathBuf::from(project_root.clone()),
|
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),
|
log_level: options.log_level.unwrap_or(IssueSeverity::Warning),
|
||||||
};
|
};
|
||||||
|
|
||||||
let issue_reporter: IssueReporterVc =
|
let issue_reporter: Vc<Box<dyn IssueReporter>> =
|
||||||
ConsoleUiVc::new(TransientInstance::new(log_options)).into();
|
Vc::upcast(ConsoleUi::new(TransientInstance::new(log_options)));
|
||||||
let node_fs = node_fs(&project_root, issue_reporter);
|
let node_fs = node_fs(project_root.clone(), issue_reporter);
|
||||||
let node_root = node_fs.root().join(".next");
|
let node_root = node_fs.root().join(".next".to_string());
|
||||||
let client_fs = client_fs(&project_root, issue_reporter);
|
let client_fs = client_fs(project_root.clone(), issue_reporter);
|
||||||
let client_root = client_fs.root().join(".next");
|
let client_root = client_fs.root().join(".next".to_string());
|
||||||
// TODO(alexkirsz) This should accept a URL for assetPrefix.
|
// 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 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_root.strip_prefix(&workspace_root).unwrap();
|
||||||
let project_relative = project_relative
|
let project_relative = project_relative
|
||||||
.strip_prefix(MAIN_SEPARATOR)
|
.strip_prefix(MAIN_SEPARATOR)
|
||||||
.unwrap_or(project_relative)
|
.unwrap_or(project_relative)
|
||||||
.replace(MAIN_SEPARATOR, "/");
|
.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_root_ref = node_root.await?;
|
||||||
|
|
||||||
let node_execution_chunking_context = DevChunkingContextVc::builder(
|
let node_execution_chunking_context = Vc::upcast(
|
||||||
project_root,
|
DevChunkingContext::builder(
|
||||||
node_root,
|
project_root,
|
||||||
node_root.join("chunks"),
|
node_root,
|
||||||
node_root.join("assets"),
|
node_root.join("chunks".to_string()),
|
||||||
node_build_environment(),
|
node_root.join("assets".to_string()),
|
||||||
)
|
node_build_environment(),
|
||||||
.build()
|
)
|
||||||
.into();
|
.build(),
|
||||||
|
);
|
||||||
|
|
||||||
let env = load_env(project_root);
|
let env = load_env(project_root);
|
||||||
|
|
||||||
let execution_context =
|
let execution_context =
|
||||||
ExecutionContextVc::new(project_root, node_execution_chunking_context, env);
|
ExecutionContext::new(project_root, node_execution_chunking_context, env);
|
||||||
let next_config = load_next_config(execution_context.with_layer("next_config"));
|
let next_config = load_next_config(execution_context.with_layer("next_config".to_string()));
|
||||||
|
|
||||||
let mode = NextMode::Build;
|
let mode = NextMode::Build;
|
||||||
let client_compile_time_info = get_client_compile_time_info(mode, browserslist_query);
|
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.
|
// 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 next_router_root = next_router_fs.root();
|
||||||
let page_entries = get_page_entries(
|
let page_entries = get_page_entries(
|
||||||
next_router_root,
|
next_router_root,
|
||||||
|
@ -169,12 +167,8 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
||||||
.try_join()
|
.try_join()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let app_client_references_by_entry = ClientReferencesByEntryVc::new(AssetsVc::cell(
|
let app_client_references_by_entry = ClientReferencesByEntry::new(Vc::cell(
|
||||||
app_rsc_entries
|
app_rsc_entries.iter().copied().map(Vc::upcast).collect(),
|
||||||
.iter()
|
|
||||||
.copied()
|
|
||||||
.map(|entry| entry.into())
|
|
||||||
.collect(),
|
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -228,12 +222,8 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// TODO(alexkirsz) Handle dynamic entries and dynamic chunks.
|
// TODO(alexkirsz) Handle dynamic entries and dynamic chunks.
|
||||||
let _dynamic_entries = NextDynamicEntriesVc::from_entries(AssetsVc::cell(
|
let _dynamic_entries = NextDynamicEntries::from_entries(Vc::cell(
|
||||||
all_node_entries
|
all_node_entries.iter().copied().map(Vc::upcast).collect(),
|
||||||
.iter()
|
|
||||||
.copied()
|
|
||||||
.map(|entry| entry.into())
|
|
||||||
.collect(),
|
|
||||||
))
|
))
|
||||||
.await?;
|
.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
|
// TODO(alexkirsz) This should be the same chunking context. The layer should
|
||||||
// be applied on the AssetContext level instead.
|
// be applied on the AssetContext level instead.
|
||||||
let rsc_chunking_context = server_chunking_context.with_layer("rsc");
|
let rsc_chunking_context = server_chunking_context.with_layer("rsc".to_string());
|
||||||
let ssr_chunking_context = server_chunking_context.with_layer("ssr");
|
let ssr_chunking_context = server_chunking_context.with_layer("ssr".to_string());
|
||||||
let (Some(rsc_chunking_context), Some(ssr_chunking_context)) = (
|
let (Some(rsc_chunking_context), Some(ssr_chunking_context)) = (
|
||||||
BuildChunkingContextVc::resolve_from(rsc_chunking_context).await?,
|
Vc::try_resolve_downcast_type::<BuildChunkingContext>(rsc_chunking_context).await?,
|
||||||
BuildChunkingContextVc::resolve_from(ssr_chunking_context).await?,
|
Vc::try_resolve_downcast_type::<BuildChunkingContext>(ssr_chunking_context).await?,
|
||||||
) else {
|
) else {
|
||||||
bail!("with_layer should not change the type of the chunking context");
|
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 all_chunks = vec![];
|
||||||
|
|
||||||
let mut build_manifest: BuildManifest = Default::default();
|
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
|
// 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
|
// in manifests. It will be added back on the client through the chunk_base_path
|
||||||
// mechanism.
|
// 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?;
|
let client_relative_path_ref = client_relative_path.await?;
|
||||||
|
|
||||||
// PAGE CHUNKING
|
// PAGE CHUNKING
|
||||||
|
|
||||||
let mut pages_manifest: PagesManifest = Default::default();
|
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?;
|
let pages_manifest_dir_path = pages_manifest_path.parent().await?;
|
||||||
|
|
||||||
compute_page_entries_chunks(
|
compute_page_entries_chunks(
|
||||||
|
@ -300,10 +290,10 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
||||||
// APP CHUNKING
|
// APP CHUNKING
|
||||||
|
|
||||||
let mut app_build_manifest = AppBuildManifest::default();
|
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 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?;
|
let app_paths_manifest_dir_path = app_paths_manifest_path.parent().await?;
|
||||||
|
|
||||||
// APP CLIENT REFERENCES CHUNKING
|
// APP CLIENT REFERENCES CHUNKING
|
||||||
|
@ -325,7 +315,7 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
||||||
&app_client_references_chunks,
|
&app_client_references_chunks,
|
||||||
rsc_chunking_context,
|
rsc_chunking_context,
|
||||||
client_chunking_context,
|
client_chunking_context,
|
||||||
ssr_chunking_context.into(),
|
Vc::upcast(ssr_chunking_context),
|
||||||
node_root,
|
node_root,
|
||||||
&client_relative_path_ref,
|
&client_relative_path_ref,
|
||||||
&app_paths_manifest_dir_path,
|
&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_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(
|
completions.push(
|
||||||
ssg_manifest_fs_path.write(
|
ssg_manifest_fs_path.write(
|
||||||
FileContent::Content(
|
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_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(
|
completions.push(
|
||||||
client_manifest_fs_path.write(
|
client_manifest_fs_path.write(
|
||||||
FileContent::Content(
|
FileContent::Content(
|
||||||
|
@ -422,23 +412,23 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
||||||
// experimental-edge pages?
|
// experimental-edge pages?
|
||||||
completions.push(write_manifest(
|
completions.push(write_manifest(
|
||||||
MiddlewaresManifest::default(),
|
MiddlewaresManifest::default(),
|
||||||
node_root.join("server/middleware-manifest.json"),
|
node_root.join("server/middleware-manifest.json".to_string()),
|
||||||
)?);
|
)?);
|
||||||
completions.push(write_manifest(
|
completions.push(write_manifest(
|
||||||
NextFontManifest::default(),
|
NextFontManifest::default(),
|
||||||
node_root.join("server/next-font-manifest.json"),
|
node_root.join("server/next-font-manifest.json".to_string()),
|
||||||
)?);
|
)?);
|
||||||
completions.push(write_manifest(
|
completions.push(write_manifest(
|
||||||
FontManifest::default(),
|
FontManifest::default(),
|
||||||
node_root.join("server/font-manifest.json"),
|
node_root.join("server/font-manifest.json".to_string()),
|
||||||
)?);
|
)?);
|
||||||
completions.push(write_manifest(
|
completions.push(write_manifest(
|
||||||
ServerReferenceManifest::default(),
|
ServerReferenceManifest::default(),
|
||||||
node_root.join("server/server-reference-manifest.json"),
|
node_root.join("server/server-reference-manifest.json".to_string()),
|
||||||
)?);
|
)?);
|
||||||
completions.push(write_manifest(
|
completions.push(write_manifest(
|
||||||
ReactLoadableManifest::default(),
|
ReactLoadableManifest::default(),
|
||||||
node_root.join("react-loadable-manifest.json"),
|
node_root.join("react-loadable-manifest.json".to_string()),
|
||||||
)?);
|
)?);
|
||||||
|
|
||||||
completions.push(
|
completions.push(
|
||||||
|
@ -451,45 +441,49 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
||||||
.await?,
|
.await?,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(CompletionsVc::all(completions))
|
Ok(Completions::all(completions))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn workspace_fs(
|
async fn workspace_fs(
|
||||||
workspace_root: &str,
|
workspace_root: String,
|
||||||
issue_reporter: IssueReporterVc,
|
issue_reporter: Vc<Box<dyn IssueReporter>>,
|
||||||
) -> Result<FileSystemVc> {
|
) -> Result<Vc<Box<dyn FileSystem>>> {
|
||||||
let disk_fs = DiskFileSystemVc::new("workspace".to_string(), workspace_root.to_string());
|
let disk_fs = DiskFileSystem::new("workspace".to_string(), workspace_root.to_string());
|
||||||
handle_issues(disk_fs, issue_reporter).await?;
|
handle_issues(disk_fs, issue_reporter).await?;
|
||||||
Ok(disk_fs.into())
|
Ok(Vc::upcast(disk_fs))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn node_fs(node_root: &str, issue_reporter: IssueReporterVc) -> Result<FileSystemVc> {
|
async fn node_fs(
|
||||||
let disk_fs = DiskFileSystemVc::new("node".to_string(), node_root.to_string());
|
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?;
|
handle_issues(disk_fs, issue_reporter).await?;
|
||||||
Ok(disk_fs.into())
|
Ok(Vc::upcast(disk_fs))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn client_fs(client_root: &str, issue_reporter: IssueReporterVc) -> Result<FileSystemVc> {
|
async fn client_fs(
|
||||||
let disk_fs = DiskFileSystemVc::new("client".to_string(), client_root.to_string());
|
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?;
|
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>(
|
async fn handle_issues<T>(source: Vc<T>, issue_reporter: Vc<Box<dyn IssueReporter>>) -> Result<()> {
|
||||||
source: T,
|
let issues = source
|
||||||
issue_reporter: IssueReporterVc,
|
.peek_issues_with_path()
|
||||||
) -> Result<()> {
|
|
||||||
let issues = IssueVc::peek_issues_with_path(source)
|
|
||||||
.await?
|
.await?
|
||||||
.strongly_consistent()
|
.strongly_consistent()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let has_fatal = issue_reporter.report_issues(
|
let has_fatal = issue_reporter.report_issues(
|
||||||
TransientInstance::new(issues.clone()),
|
TransientInstance::new(issues.clone()),
|
||||||
TransientValue::new(source.into()),
|
TransientValue::new(source.node),
|
||||||
);
|
);
|
||||||
|
|
||||||
if *has_fatal.await? {
|
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
|
/// Emits all assets transitively reachable from the given chunks, that are
|
||||||
/// inside the node root or the client root.
|
/// inside the node root or the client root.
|
||||||
async fn emit_all_assets(
|
async fn emit_all_assets(
|
||||||
chunks: Vec<OutputAssetVc>,
|
chunks: Vec<Vc<Box<dyn OutputAsset>>>,
|
||||||
node_root: &FileSystemPath,
|
node_root: &FileSystemPath,
|
||||||
client_relative_path: FileSystemPathVc,
|
client_relative_path: Vc<FileSystemPath>,
|
||||||
client_output_path: FileSystemPathVc,
|
client_output_path: Vc<FileSystemPath>,
|
||||||
) -> Result<CompletionVc> {
|
) -> Result<Vc<Completion>> {
|
||||||
let all_assets = all_assets_from_entries(OutputAssetsVc::cell(chunks)).await?;
|
let all_assets = all_assets_from_entries(Vc::cell(chunks)).await?;
|
||||||
Ok(CompletionsVc::all(
|
Ok(Completions::all(
|
||||||
all_assets
|
all_assets
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.map(|asset| async move {
|
.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));
|
return Ok(emit(asset));
|
||||||
} else if asset
|
} else if asset
|
||||||
.ident()
|
.ident()
|
||||||
.path()
|
.path()
|
||||||
.await?
|
.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
|
// Client assets are emitted to the client output path, which is prefixed with
|
||||||
// _next. We need to rebase them to remove that prefix.
|
// _next. We need to rebase them to remove that prefix.
|
||||||
return Ok(emit_rebase(asset, client_relative_path, client_output_path));
|
return Ok(emit_rebase(asset, client_relative_path, client_output_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(CompletionVc::immutable())
|
Ok(Completion::immutable())
|
||||||
})
|
})
|
||||||
.try_join()
|
.try_join()
|
||||||
.await?,
|
.await?,
|
||||||
|
@ -534,12 +528,16 @@ async fn emit_all_assets(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn emit(asset: AssetVc) -> CompletionVc {
|
fn emit(asset: Vc<Box<dyn Asset>>) -> Vc<Completion> {
|
||||||
asset.content().write(asset.ident().path())
|
asset.content().write(asset.ident().path())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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
|
asset
|
||||||
.content()
|
.content()
|
||||||
.write(rebase(asset.ident().path(), from, to))
|
.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
|
/// Walks the asset graph from multiple assets and collect all referenced
|
||||||
/// assets.
|
/// assets.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn all_assets_from_entries(entries: OutputAssetsVc) -> Result<AssetsVc> {
|
async fn all_assets_from_entries(entries: Vc<OutputAssets>) -> Result<Vc<Assets>> {
|
||||||
Ok(AssetsVc::cell(
|
Ok(Vc::cell(
|
||||||
AdjacencyMap::new()
|
AdjacencyMap::new()
|
||||||
.skip_duplicates()
|
.skip_duplicates()
|
||||||
.visit(
|
.visit(
|
||||||
entries.await?.iter().copied().map(Into::into),
|
entries.await?.iter().copied().map(Vc::upcast),
|
||||||
get_referenced_assets,
|
get_referenced_assets,
|
||||||
)
|
)
|
||||||
.await
|
.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.
|
/// 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
|
Ok(asset
|
||||||
.references()
|
.references()
|
||||||
.await?
|
.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
|
/// Writes a manifest to disk. This consumes the manifest to ensure we don't
|
||||||
/// write to it afterwards.
|
/// 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
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,45 +6,38 @@ use next_core::{
|
||||||
get_client_module_options_context, get_client_resolve_options_context,
|
get_client_module_options_context, get_client_resolve_options_context,
|
||||||
get_client_runtime_entries, ClientContextType,
|
get_client_runtime_entries, ClientContextType,
|
||||||
},
|
},
|
||||||
next_config::NextConfigVc,
|
next_config::NextConfig,
|
||||||
next_dynamic::NextDynamicTransitionVc,
|
next_dynamic::NextDynamicTransition,
|
||||||
next_server::{
|
next_server::{
|
||||||
get_server_module_options_context, get_server_resolve_options_context,
|
get_server_module_options_context, get_server_resolve_options_context,
|
||||||
get_server_runtime_entries, ServerContextType,
|
get_server_runtime_entries, ServerContextType,
|
||||||
},
|
},
|
||||||
pages_structure::{
|
pages_structure::{
|
||||||
find_pages_structure, PagesDirectoryStructure, PagesDirectoryStructureVc, PagesStructure,
|
find_pages_structure, PagesDirectoryStructure, PagesStructure, PagesStructureItem,
|
||||||
PagesStructureItem, PagesStructureVc,
|
|
||||||
},
|
},
|
||||||
pathname_for_path, PathType,
|
pathname_for_path, PathType,
|
||||||
};
|
};
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{
|
turbo::{tasks::Value, tasks_env::ProcessEnv, tasks_fs::FileSystemPath},
|
||||||
tasks::{primitives::StringVc, Value},
|
|
||||||
tasks_env::ProcessEnvVc,
|
|
||||||
tasks_fs::{FileSystemPath, FileSystemPathVc},
|
|
||||||
},
|
|
||||||
turbopack::{
|
turbopack::{
|
||||||
build::BuildChunkingContextVc,
|
build::BuildChunkingContext,
|
||||||
core::{
|
core::{
|
||||||
asset::Asset,
|
asset::Asset,
|
||||||
chunk::{ChunkableModule, ChunkingContext, EvaluatableAssetsVc},
|
chunk::{ChunkableModule, ChunkingContext, EvaluatableAssets},
|
||||||
compile_time_info::CompileTimeInfoVc,
|
compile_time_info::CompileTimeInfo,
|
||||||
context::{AssetContext, AssetContextVc},
|
context::AssetContext,
|
||||||
file_source::FileSourceVc,
|
file_source::FileSource,
|
||||||
output::OutputAssetVc,
|
output::OutputAsset,
|
||||||
reference_type::{EntryReferenceSubType, ReferenceType},
|
reference_type::{EntryReferenceSubType, ReferenceType},
|
||||||
source::SourceVc,
|
source::Source,
|
||||||
},
|
},
|
||||||
ecmascript::{
|
ecmascript::{
|
||||||
chunk::{EcmascriptChunkPlaceableVc, EcmascriptChunkingContextVc},
|
chunk::{EcmascriptChunkPlaceable, EcmascriptChunkingContext},
|
||||||
EcmascriptModuleAssetVc,
|
EcmascriptModuleAsset,
|
||||||
},
|
|
||||||
node::execution_context::ExecutionContextVc,
|
|
||||||
turbopack::{
|
|
||||||
transition::{ContextTransitionVc, TransitionsByNameVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
|
node::execution_context::ExecutionContext,
|
||||||
|
turbopack::{transition::ContextTransition, ModuleAssetContext},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -52,22 +45,22 @@ use crate::manifests::{BuildManifest, PagesManifest};
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub struct PageEntries {
|
pub struct PageEntries {
|
||||||
pub entries: Vec<PageEntryVc>,
|
pub entries: Vec<Vc<PageEntry>>,
|
||||||
pub ssr_runtime_entries: EvaluatableAssetsVc,
|
pub ssr_runtime_entries: Vc<EvaluatableAssets>,
|
||||||
pub client_runtime_entries: EvaluatableAssetsVc,
|
pub client_runtime_entries: Vc<EvaluatableAssets>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes all the page entries within the given project root.
|
/// Computes all the page entries within the given project root.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_page_entries(
|
pub async fn get_page_entries(
|
||||||
next_router_root: FileSystemPathVc,
|
next_router_root: Vc<FileSystemPath>,
|
||||||
project_root: FileSystemPathVc,
|
project_root: Vc<FileSystemPath>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
env: ProcessEnvVc,
|
env: Vc<Box<dyn ProcessEnv>>,
|
||||||
client_compile_time_info: CompileTimeInfoVc,
|
client_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
server_compile_time_info: CompileTimeInfoVc,
|
server_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
) -> Result<PageEntriesVc> {
|
) -> Result<Vc<PageEntries>> {
|
||||||
let pages_structure = find_pages_structure(
|
let pages_structure = find_pages_structure(
|
||||||
project_root,
|
project_root,
|
||||||
next_router_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 {
|
let pages_dir = if let Some(pages) = pages_structure.await?.pages {
|
||||||
pages.project_path().resolve().await?
|
pages.project_path().resolve().await?
|
||||||
} else {
|
} else {
|
||||||
project_root.join("pages")
|
project_root.join("pages".to_string())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mode = NextMode::Build;
|
let mode = NextMode::Build;
|
||||||
|
@ -102,28 +95,27 @@ pub async fn get_page_entries(
|
||||||
execution_context,
|
execution_context,
|
||||||
);
|
);
|
||||||
|
|
||||||
let client_transition = ContextTransitionVc::new(
|
let client_transition = ContextTransition::new(
|
||||||
client_compile_time_info,
|
client_compile_time_info,
|
||||||
client_module_options_context,
|
client_module_options_context,
|
||||||
client_resolve_options_context,
|
client_resolve_options_context,
|
||||||
);
|
);
|
||||||
|
|
||||||
let transitions = TransitionsByNameVc::cell(
|
let transitions = Vc::cell(
|
||||||
[(
|
[(
|
||||||
"next-dynamic".to_string(),
|
"next-dynamic".to_string(),
|
||||||
NextDynamicTransitionVc::new(client_transition).into(),
|
Vc::upcast(NextDynamicTransition::new(client_transition)),
|
||||||
)]
|
)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let client_module_context: AssetContextVc = ModuleAssetContextVc::new(
|
let client_module_context: Vc<Box<dyn AssetContext>> = Vc::upcast(ModuleAssetContext::new(
|
||||||
transitions,
|
transitions,
|
||||||
client_compile_time_info,
|
client_compile_time_info,
|
||||||
client_module_options_context,
|
client_module_options_context,
|
||||||
client_resolve_options_context,
|
client_resolve_options_context,
|
||||||
)
|
));
|
||||||
.into();
|
|
||||||
|
|
||||||
let client_runtime_entries = get_client_runtime_entries(
|
let client_runtime_entries = get_client_runtime_entries(
|
||||||
project_root,
|
project_root,
|
||||||
|
@ -150,13 +142,12 @@ pub async fn get_page_entries(
|
||||||
next_config,
|
next_config,
|
||||||
);
|
);
|
||||||
|
|
||||||
let ssr_module_context = ModuleAssetContextVc::new(
|
let ssr_module_context = Vc::upcast(ModuleAssetContext::new(
|
||||||
transitions,
|
transitions,
|
||||||
server_compile_time_info,
|
server_compile_time_info,
|
||||||
ssr_module_options_context,
|
ssr_module_options_context,
|
||||||
ssr_resolve_options_context,
|
ssr_resolve_options_context,
|
||||||
)
|
));
|
||||||
.into();
|
|
||||||
|
|
||||||
let ssr_runtime_entries =
|
let ssr_runtime_entries =
|
||||||
get_server_runtime_entries(project_root, env, ssr_ty, mode, next_config);
|
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(
|
async fn get_page_entries_for_root_directory(
|
||||||
ssr_module_context: AssetContextVc,
|
ssr_module_context: Vc<Box<dyn AssetContext>>,
|
||||||
client_module_context: AssetContextVc,
|
client_module_context: Vc<Box<dyn AssetContext>>,
|
||||||
pages_structure: PagesStructureVc,
|
pages_structure: Vc<PagesStructure>,
|
||||||
next_router_root: FileSystemPathVc,
|
next_router_root: Vc<FileSystemPath>,
|
||||||
) -> Result<Vec<PageEntryVc>> {
|
) -> Result<Vec<Vc<PageEntry>>> {
|
||||||
let PagesStructure {
|
let PagesStructure {
|
||||||
app,
|
app,
|
||||||
document,
|
document,
|
||||||
|
@ -199,7 +190,7 @@ async fn get_page_entries_for_root_directory(
|
||||||
entries.push(get_page_entry_for_file(
|
entries.push(get_page_entry_for_file(
|
||||||
ssr_module_context,
|
ssr_module_context,
|
||||||
client_module_context,
|
client_module_context,
|
||||||
FileSourceVc::new(app.project_path).into(),
|
Vc::upcast(FileSource::new(app.project_path)),
|
||||||
next_router_root,
|
next_router_root,
|
||||||
app.next_router_path,
|
app.next_router_path,
|
||||||
));
|
));
|
||||||
|
@ -209,7 +200,7 @@ async fn get_page_entries_for_root_directory(
|
||||||
entries.push(get_page_entry_for_file(
|
entries.push(get_page_entry_for_file(
|
||||||
ssr_module_context,
|
ssr_module_context,
|
||||||
client_module_context,
|
client_module_context,
|
||||||
FileSourceVc::new(document.project_path).into(),
|
Vc::upcast(FileSource::new(document.project_path)),
|
||||||
next_router_root,
|
next_router_root,
|
||||||
document.next_router_path,
|
document.next_router_path,
|
||||||
));
|
));
|
||||||
|
@ -220,7 +211,7 @@ async fn get_page_entries_for_root_directory(
|
||||||
entries.push(get_page_entry_for_file(
|
entries.push(get_page_entry_for_file(
|
||||||
ssr_module_context,
|
ssr_module_context,
|
||||||
client_module_context,
|
client_module_context,
|
||||||
FileSourceVc::new(error.project_path).into(),
|
Vc::upcast(FileSource::new(error.project_path)),
|
||||||
next_router_root,
|
next_router_root,
|
||||||
error.next_router_path,
|
error.next_router_path,
|
||||||
));
|
));
|
||||||
|
@ -252,11 +243,11 @@ async fn get_page_entries_for_root_directory(
|
||||||
|
|
||||||
#[async_recursion::async_recursion]
|
#[async_recursion::async_recursion]
|
||||||
async fn get_page_entries_for_directory(
|
async fn get_page_entries_for_directory(
|
||||||
ssr_module_context: AssetContextVc,
|
ssr_module_context: Vc<Box<dyn AssetContext>>,
|
||||||
client_module_context: AssetContextVc,
|
client_module_context: Vc<Box<dyn AssetContext>>,
|
||||||
pages_structure: PagesDirectoryStructureVc,
|
pages_structure: Vc<PagesDirectoryStructure>,
|
||||||
next_router_root: FileSystemPathVc,
|
next_router_root: Vc<FileSystemPath>,
|
||||||
entries: &mut Vec<PageEntryVc>,
|
entries: &mut Vec<Vc<PageEntry>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let PagesDirectoryStructure {
|
let PagesDirectoryStructure {
|
||||||
ref items,
|
ref items,
|
||||||
|
@ -273,7 +264,7 @@ async fn get_page_entries_for_directory(
|
||||||
entries.push(get_page_entry_for_file(
|
entries.push(get_page_entry_for_file(
|
||||||
ssr_module_context,
|
ssr_module_context,
|
||||||
client_module_context,
|
client_module_context,
|
||||||
FileSourceVc::new(project_path).into(),
|
Vc::upcast(FileSource::new(project_path)),
|
||||||
next_router_root,
|
next_router_root,
|
||||||
next_router_path,
|
next_router_path,
|
||||||
));
|
));
|
||||||
|
@ -297,21 +288,21 @@ async fn get_page_entries_for_directory(
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub struct PageEntry {
|
pub struct PageEntry {
|
||||||
/// The pathname of the page.
|
/// The pathname of the page.
|
||||||
pub pathname: StringVc,
|
pub pathname: Vc<String>,
|
||||||
/// The Node.js SSR entry module asset.
|
/// The Node.js SSR entry module asset.
|
||||||
pub ssr_module: EcmascriptChunkPlaceableVc,
|
pub ssr_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
/// The client entry module asset.
|
/// The client entry module asset.
|
||||||
pub client_module: EcmascriptModuleAssetVc,
|
pub client_module: Vc<EcmascriptModuleAsset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn get_page_entry_for_file(
|
async fn get_page_entry_for_file(
|
||||||
ssr_module_context: AssetContextVc,
|
ssr_module_context: Vc<Box<dyn AssetContext>>,
|
||||||
client_module_context: AssetContextVc,
|
client_module_context: Vc<Box<dyn AssetContext>>,
|
||||||
source: SourceVc,
|
source: Vc<Box<dyn Source>>,
|
||||||
next_router_root: FileSystemPathVc,
|
next_router_root: Vc<FileSystemPath>,
|
||||||
next_router_path: FileSystemPathVc,
|
next_router_path: Vc<FileSystemPath>,
|
||||||
) -> Result<PageEntryVc> {
|
) -> Result<Vc<PageEntry>> {
|
||||||
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
||||||
|
|
||||||
let pathname = pathname_for_path(next_router_root, next_router_path, PathType::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 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");
|
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");
|
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.
|
/// Computes the pathname for a given path.
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
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
|
/// Computes the chunks of page entries, adds their paths to the corresponding
|
||||||
/// manifests, and pushes the assets to the `all_chunks` vec.
|
/// manifests, and pushes the assets to the `all_chunks` vec.
|
||||||
pub async fn compute_page_entries_chunks(
|
pub async fn compute_page_entries_chunks(
|
||||||
page_entries: &PageEntries,
|
page_entries: &PageEntries,
|
||||||
client_chunking_context: EcmascriptChunkingContextVc,
|
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
ssr_chunking_context: BuildChunkingContextVc,
|
ssr_chunking_context: Vc<BuildChunkingContext>,
|
||||||
node_root: FileSystemPathVc,
|
node_root: Vc<FileSystemPath>,
|
||||||
pages_manifest_dir_path: &FileSystemPath,
|
pages_manifest_dir_path: &FileSystemPath,
|
||||||
client_relative_path: &FileSystemPath,
|
client_relative_path: &FileSystemPath,
|
||||||
pages_manifest: &mut PagesManifest,
|
pages_manifest: &mut PagesManifest,
|
||||||
build_manifest: &mut BuildManifest,
|
build_manifest: &mut BuildManifest,
|
||||||
all_chunks: &mut Vec<OutputAssetVc>,
|
all_chunks: &mut Vec<Vc<Box<dyn OutputAsset>>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for page_entry in page_entries.entries.iter() {
|
for page_entry in page_entries.entries.iter() {
|
||||||
let page_entry = page_entry.await?;
|
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 asset_path: String = get_asset_path_from_pathname(&pathname, ".js");
|
||||||
|
|
||||||
let ssr_entry_chunk = ssr_chunking_context.entry_chunk(
|
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_entry.ssr_module,
|
||||||
page_entries.ssr_runtime_entries,
|
page_entries.ssr_runtime_entries,
|
||||||
);
|
);
|
||||||
|
@ -377,13 +372,13 @@ pub async fn compute_page_entries_chunks(
|
||||||
|
|
||||||
let client_entry_chunk = page_entry
|
let client_entry_chunk = page_entry
|
||||||
.client_module
|
.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(
|
let client_chunks = client_chunking_context.evaluated_chunk_group(
|
||||||
client_entry_chunk,
|
client_entry_chunk,
|
||||||
page_entries
|
page_entries
|
||||||
.client_runtime_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
|
let build_manifest_pages_entry = build_manifest
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
"check": "tsc --noEmit"
|
"check": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/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-230713.3",
|
"@vercel/turbopack-node": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230716.2",
|
||||||
"anser": "^2.1.1",
|
"anser": "^2.1.1",
|
||||||
"css.escape": "^1.5.1",
|
"css.escape": "^1.5.1",
|
||||||
"next": "*",
|
"next": "*",
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
use std::collections::HashMap;
|
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;
|
pub mod next_server_component_transition;
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct LayoutSegment {
|
pub struct LayoutSegment {
|
||||||
pub files: HashMap<String, FileSystemPathVc>,
|
pub files: HashMap<String, Vc<FileSystemPath>>,
|
||||||
pub target: FileSystemPathVc,
|
pub target: Vc<FileSystemPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(transparent)]
|
#[turbo_tasks::value(transparent)]
|
||||||
pub struct LayoutSegments(Vec<LayoutSegmentVc>);
|
pub struct LayoutSegments(Vec<Vc<LayoutSegment>>);
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::FileSystemPathVc,
|
turbo::tasks_fs::FileSystemPath,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{compile_time_info::CompileTimeInfoVc, module::ModuleVc},
|
core::{compile_time_info::CompileTimeInfo, module::Module},
|
||||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
ecmascript::chunk::EcmascriptChunkPlaceable,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
module_options::ModuleOptionsContextVc,
|
module_options::ModuleOptionsContext, resolve_options_context::ResolveOptionsContext,
|
||||||
resolve_options_context::ResolveOptionsContextVc,
|
transition::Transition, ModuleAssetContext,
|
||||||
transition::{Transition, TransitionVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -20,10 +19,10 @@ use crate::next_client_component::{
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextServerComponentTransition {
|
pub struct NextServerComponentTransition {
|
||||||
pub rsc_compile_time_info: CompileTimeInfoVc,
|
pub rsc_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
pub rsc_module_options_context: ModuleOptionsContextVc,
|
pub rsc_module_options_context: Vc<ModuleOptionsContext>,
|
||||||
pub rsc_resolve_options_context: ResolveOptionsContextVc,
|
pub rsc_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||||
pub server_root: FileSystemPathVc,
|
pub server_root: Vc<FileSystemPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
|
@ -31,48 +30,52 @@ impl Transition for NextServerComponentTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_compile_time_info(
|
fn process_compile_time_info(
|
||||||
&self,
|
&self,
|
||||||
_compile_time_info: CompileTimeInfoVc,
|
_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
) -> CompileTimeInfoVc {
|
) -> Vc<CompileTimeInfo> {
|
||||||
self.rsc_compile_time_info
|
self.rsc_compile_time_info
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_module_options_context(
|
fn process_module_options_context(
|
||||||
&self,
|
&self,
|
||||||
_context: ModuleOptionsContextVc,
|
_context: Vc<ModuleOptionsContext>,
|
||||||
) -> ModuleOptionsContextVc {
|
) -> Vc<ModuleOptionsContext> {
|
||||||
self.rsc_module_options_context
|
self.rsc_module_options_context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_resolve_options_context(
|
fn process_resolve_options_context(
|
||||||
&self,
|
&self,
|
||||||
_context: ResolveOptionsContextVc,
|
_context: Vc<ResolveOptionsContext>,
|
||||||
) -> ResolveOptionsContextVc {
|
) -> Vc<ResolveOptionsContext> {
|
||||||
self.rsc_resolve_options_context
|
self.rsc_resolve_options_context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn process_module(
|
async fn process_module(
|
||||||
&self,
|
&self,
|
||||||
module: ModuleVc,
|
module: Vc<Box<dyn Module>>,
|
||||||
_context: ModuleAssetContextVc,
|
_context: Vc<ModuleAssetContext>,
|
||||||
) -> Result<ModuleVc> {
|
) -> Result<Vc<Box<dyn Module>>> {
|
||||||
let Some(asset) = EcmascriptChunkPlaceableVc::resolve_from(module).await? else {
|
let Some(asset) =
|
||||||
|
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(module).await?
|
||||||
|
else {
|
||||||
bail!("Not an ecmascript module");
|
bail!("Not an ecmascript module");
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(WithChunkingContextScopeAsset {
|
Ok(Vc::upcast(
|
||||||
asset: WithClientChunksAsset {
|
WithChunkingContextScopeAsset {
|
||||||
asset,
|
asset: Vc::upcast(
|
||||||
// next.js code already adds _next prefix
|
WithClientChunksAsset {
|
||||||
server_root: self.server_root.join("_next"),
|
asset,
|
||||||
|
// next.js code already adds _next prefix
|
||||||
|
server_root: self.server_root.join("_next".to_string()),
|
||||||
|
}
|
||||||
|
.cell(),
|
||||||
|
),
|
||||||
|
layer: "rsc".to_string(),
|
||||||
}
|
}
|
||||||
.cell()
|
.cell(),
|
||||||
.into(),
|
))
|
||||||
layer: "rsc".to_string(),
|
|
||||||
}
|
|
||||||
.cell()
|
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,28 +7,26 @@ use swc_core::{
|
||||||
common::{source_map::Pos, Span, Spanned},
|
common::{source_map::Pos, Span, Spanned},
|
||||||
ecma::ast::{Expr, Ident, Program},
|
ecma::ast::{Expr, Ident, Program},
|
||||||
};
|
};
|
||||||
use turbo_tasks::{primitives::StringVc, trace::TraceRawVcs, TryJoinIterExt};
|
use turbo_tasks::{trace::TraceRawVcs, TryJoinIterExt, ValueDefault, Vc};
|
||||||
use turbo_tasks_fs::FileSystemPathVc;
|
use turbo_tasks_fs::FileSystemPath;
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetVc},
|
asset::Asset,
|
||||||
context::{AssetContext, AssetContextVc},
|
context::AssetContext,
|
||||||
file_source::FileSourceVc,
|
file_source::FileSource,
|
||||||
ident::AssetIdentVc,
|
ident::AssetIdent,
|
||||||
issue::{
|
issue::{Issue, IssueExt, IssueSeverity, IssueSource, OptionIssueSource},
|
||||||
Issue, IssueSeverity, IssueSeverityVc, IssueSourceVc, IssueVc, OptionIssueSourceVc,
|
module::Module,
|
||||||
},
|
|
||||||
module::ModuleVc,
|
|
||||||
reference_type::{EcmaScriptModulesReferenceSubType, ReferenceType},
|
reference_type::{EcmaScriptModulesReferenceSubType, ReferenceType},
|
||||||
},
|
},
|
||||||
ecmascript::{
|
ecmascript::{
|
||||||
analyzer::{graph::EvalContext, ConstantNumber, ConstantValue, JsValue},
|
analyzer::{graph::EvalContext, ConstantNumber, ConstantValue, JsValue},
|
||||||
parse::ParseResult,
|
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)]
|
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug, TraceRawVcs, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
@ -75,9 +73,9 @@ pub struct NextSegmentConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextSegmentConfigVc {
|
impl ValueDefault for NextSegmentConfig {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn default() -> Self {
|
pub fn value_default() -> Vc<Self> {
|
||||||
NextSegmentConfig::default().cell()
|
NextSegmentConfig::default().cell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,36 +153,36 @@ impl NextSegmentConfig {
|
||||||
/// An issue that occurred while parsing the app segment config.
|
/// An issue that occurred while parsing the app segment config.
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextSegmentConfigParsingIssue {
|
pub struct NextSegmentConfigParsingIssue {
|
||||||
ident: AssetIdentVc,
|
ident: Vc<AssetIdent>,
|
||||||
detail: StringVc,
|
detail: Vc<String>,
|
||||||
source: IssueSourceVc,
|
source: Vc<IssueSource>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Issue for NextSegmentConfigParsingIssue {
|
impl Issue for NextSegmentConfigParsingIssue {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn severity(&self) -> IssueSeverityVc {
|
fn severity(&self) -> Vc<IssueSeverity> {
|
||||||
IssueSeverity::Warning.into()
|
IssueSeverity::Warning.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn title(&self) -> StringVc {
|
fn title(&self) -> Vc<String> {
|
||||||
StringVc::cell("Unable to parse config export in source file".to_string())
|
Vc::cell("Unable to parse config export in source file".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn category(&self) -> StringVc {
|
fn category(&self) -> Vc<String> {
|
||||||
StringVc::cell("parsing".to_string())
|
Vc::cell("parsing".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn context(&self) -> FileSystemPathVc {
|
fn context(&self) -> Vc<FileSystemPath> {
|
||||||
self.ident.path()
|
self.ident.path()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn description(&self) -> StringVc {
|
fn description(&self) -> Vc<String> {
|
||||||
StringVc::cell(
|
Vc::cell(
|
||||||
"The exported configuration object in a source file need to have a very specific \
|
"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."
|
format from which some properties can be statically parsed at compiled-time."
|
||||||
.to_string(),
|
.to_string(),
|
||||||
|
@ -192,30 +190,32 @@ impl Issue for NextSegmentConfigParsingIssue {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn detail(&self) -> StringVc {
|
fn detail(&self) -> Vc<String> {
|
||||||
self.detail
|
self.detail
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn documentation_link(&self) -> StringVc {
|
fn documentation_link(&self) -> Vc<String> {
|
||||||
StringVc::cell(
|
Vc::cell(
|
||||||
"https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config"
|
"https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config"
|
||||||
.to_string(),
|
.to_string(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn source(&self) -> OptionIssueSourceVc {
|
fn source(&self) -> Vc<OptionIssueSource> {
|
||||||
OptionIssueSourceVc::some(self.source)
|
OptionIssueSource::some(self.source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn parse_segment_config_from_source(
|
pub async fn parse_segment_config_from_source(
|
||||||
module_asset: ModuleVc,
|
module_asset: Vc<Box<dyn Module>>,
|
||||||
) -> Result<NextSegmentConfigVc> {
|
) -> Result<Vc<NextSegmentConfig>> {
|
||||||
let Some(ecmascript_asset) = EcmascriptModuleAssetVc::resolve_from(module_asset).await? else {
|
let Some(ecmascript_asset) =
|
||||||
return Ok(NextSegmentConfigVc::default());
|
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(module_asset).await?
|
||||||
|
else {
|
||||||
|
return Ok(Default::default());
|
||||||
};
|
};
|
||||||
|
|
||||||
let ParseResult::Ok {
|
let ParseResult::Ok {
|
||||||
|
@ -224,7 +224,7 @@ pub async fn parse_segment_config_from_source(
|
||||||
..
|
..
|
||||||
} = &*ecmascript_asset.parse().await?
|
} = &*ecmascript_asset.parse().await?
|
||||||
else {
|
else {
|
||||||
return Ok(NextSegmentConfigVc::default());
|
return Ok(Default::default());
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut config = NextSegmentConfig::default();
|
let mut config = NextSegmentConfig::default();
|
||||||
|
@ -252,12 +252,12 @@ pub async fn parse_segment_config_from_source(
|
||||||
Ok(config.cell())
|
Ok(config.cell())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn issue_source(source: AssetVc, span: Span) -> IssueSourceVc {
|
fn issue_source(source: Vc<Box<dyn Asset>>, span: Span) -> Vc<IssueSource> {
|
||||||
IssueSourceVc::from_byte_offset(source, span.lo.to_usize(), span.hi.to_usize())
|
IssueSource::from_byte_offset(source, span.lo.to_usize(), span.hi.to_usize())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_config_value(
|
fn parse_config_value(
|
||||||
module: ModuleVc,
|
module: Vc<Box<dyn Module>>,
|
||||||
config: &mut NextSegmentConfig,
|
config: &mut NextSegmentConfig,
|
||||||
ident: &Ident,
|
ident: &Ident,
|
||||||
init: &Expr,
|
init: &Expr,
|
||||||
|
@ -268,11 +268,10 @@ fn parse_config_value(
|
||||||
let (explainer, hints) = value.explain(2, 0);
|
let (explainer, hints) = value.explain(2, 0);
|
||||||
NextSegmentConfigParsingIssue {
|
NextSegmentConfigParsingIssue {
|
||||||
ident: module.ident(),
|
ident: module.ident(),
|
||||||
detail: StringVc::cell(format!("{detail} Got {explainer}.{hints}")),
|
detail: Vc::cell(format!("{detail} Got {explainer}.{hints}")),
|
||||||
source: issue_source(module.into(), span),
|
source: issue_source(Vc::upcast(module), span),
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
.as_issue()
|
|
||||||
.emit();
|
.emit();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -370,9 +369,9 @@ fn parse_config_value(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn parse_segment_config_from_loader_tree(
|
pub async fn parse_segment_config_from_loader_tree(
|
||||||
loader_tree: LoaderTreeVc,
|
loader_tree: Vc<LoaderTree>,
|
||||||
context: AssetContextVc,
|
context: Vc<Box<dyn AssetContext>>,
|
||||||
) -> Result<NextSegmentConfigVc> {
|
) -> Result<Vc<NextSegmentConfig>> {
|
||||||
let loader_tree = loader_tree.await?;
|
let loader_tree = loader_tree.await?;
|
||||||
let components = loader_tree.components.await?;
|
let components = loader_tree.components.await?;
|
||||||
let mut config = NextSegmentConfig::default();
|
let mut config = NextSegmentConfig::default();
|
||||||
|
@ -392,7 +391,7 @@ pub async fn parse_segment_config_from_loader_tree(
|
||||||
{
|
{
|
||||||
config.apply_parent_config(
|
config.apply_parent_config(
|
||||||
&*parse_segment_config_from_source(context.process(
|
&*parse_segment_config_from_source(context.process(
|
||||||
FileSourceVc::new(component).into(),
|
Vc::upcast(FileSource::new(component)),
|
||||||
turbo_tasks::Value::new(ReferenceType::EcmaScriptModules(
|
turbo_tasks::Value::new(ReferenceType::EcmaScriptModules(
|
||||||
EcmaScriptModulesReferenceSubType::Undefined,
|
EcmaScriptModulesReferenceSubType::Undefined,
|
||||||
)),
|
)),
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,4 @@
|
||||||
use std::{
|
use std::collections::{BTreeMap, HashMap};
|
||||||
borrow::Cow,
|
|
||||||
collections::{BTreeMap, HashMap},
|
|
||||||
};
|
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use indexmap::{indexmap, map::Entry, IndexMap};
|
use indexmap::{indexmap, map::Entry, IndexMap};
|
||||||
|
@ -9,38 +6,36 @@ use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{
|
||||||
debug::ValueDebugFormat,
|
debug::ValueDebugFormat, trace::TraceRawVcs, Completion, Completions, TaskInput, ValueToString,
|
||||||
primitives::{StringVc, StringsVc},
|
Vc,
|
||||||
trace::TraceRawVcs,
|
|
||||||
CompletionVc, CompletionsVc, TaskInput, ValueToString,
|
|
||||||
};
|
};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPathVc},
|
turbo::tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPath},
|
||||||
turbopack::core::issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc},
|
turbopack::core::issue::{Issue, IssueExt, IssueSeverity},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::next_config::NextConfigVc;
|
use crate::next_config::NextConfig;
|
||||||
|
|
||||||
/// A final route in the app directory.
|
/// A final route in the app directory.
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct Components {
|
pub struct Components {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub page: Option<FileSystemPathVc>,
|
pub page: Option<Vc<FileSystemPath>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub layout: Option<FileSystemPathVc>,
|
pub layout: Option<Vc<FileSystemPath>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub error: Option<FileSystemPathVc>,
|
pub error: Option<Vc<FileSystemPath>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub loading: Option<FileSystemPathVc>,
|
pub loading: Option<Vc<FileSystemPath>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub template: Option<FileSystemPathVc>,
|
pub template: Option<Vc<FileSystemPath>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[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")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub default: Option<FileSystemPathVc>,
|
pub default: Option<Vc<FileSystemPath>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub route: Option<FileSystemPathVc>,
|
pub route: Option<Vc<FileSystemPath>>,
|
||||||
#[serde(skip_serializing_if = "Metadata::is_empty")]
|
#[serde(skip_serializing_if = "Metadata::is_empty")]
|
||||||
pub metadata: Metadata,
|
pub metadata: Metadata,
|
||||||
}
|
}
|
||||||
|
@ -76,13 +71,13 @@ impl Components {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ComponentsVc {
|
impl Components {
|
||||||
/// Returns a completion that changes when any route in the components
|
/// Returns a completion that changes when any route in the components
|
||||||
/// changes.
|
/// changes.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn routes_changed(self) -> Result<CompletionVc> {
|
pub async fn routes_changed(self: Vc<Self>) -> Result<Vc<Completion>> {
|
||||||
self.await?;
|
self.await?;
|
||||||
Ok(CompletionVc::new())
|
Ok(Completion::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,19 +85,19 @@ impl ComponentsVc {
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, TraceRawVcs)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, TraceRawVcs)]
|
||||||
pub enum MetadataWithAltItem {
|
pub enum MetadataWithAltItem {
|
||||||
Static {
|
Static {
|
||||||
path: FileSystemPathVc,
|
path: Vc<FileSystemPath>,
|
||||||
alt_path: Option<FileSystemPathVc>,
|
alt_path: Option<Vc<FileSystemPath>>,
|
||||||
},
|
},
|
||||||
Dynamic {
|
Dynamic {
|
||||||
path: FileSystemPathVc,
|
path: Vc<FileSystemPath>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single metadata file.
|
/// A single metadata file.
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, TraceRawVcs)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, TraceRawVcs)]
|
||||||
pub enum MetadataItem {
|
pub enum MetadataItem {
|
||||||
Static { path: FileSystemPathVc },
|
Static { path: Vc<FileSystemPath> },
|
||||||
Dynamic { path: FileSystemPathVc },
|
Dynamic { path: Vc<FileSystemPath> },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata file that can be placed in any segment of the app directory.
|
/// Metadata file that can be placed in any segment of the app directory.
|
||||||
|
@ -184,16 +179,16 @@ impl GlobalMetadata {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DirectoryTree {
|
pub struct DirectoryTree {
|
||||||
/// key is e.g. "dashboard", "(dashboard)", "@slot"
|
/// key is e.g. "dashboard", "(dashboard)", "@slot"
|
||||||
pub subdirectories: BTreeMap<String, DirectoryTreeVc>,
|
pub subdirectories: BTreeMap<String, Vc<DirectoryTree>>,
|
||||||
pub components: ComponentsVc,
|
pub components: Vc<Components>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl DirectoryTreeVc {
|
impl DirectoryTree {
|
||||||
/// Returns a completion that changes when any route in the whole tree
|
/// Returns a completion that changes when any route in the whole tree
|
||||||
/// changes.
|
/// changes.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn routes_changed(self) -> Result<CompletionVc> {
|
pub async fn routes_changed(self: Vc<Self>) -> Result<Vc<Completion>> {
|
||||||
let DirectoryTree {
|
let DirectoryTree {
|
||||||
subdirectories,
|
subdirectories,
|
||||||
components,
|
components,
|
||||||
|
@ -203,54 +198,57 @@ impl DirectoryTreeVc {
|
||||||
for child in subdirectories.values() {
|
for child in subdirectories.values() {
|
||||||
children.push(child.routes_changed());
|
children.push(child.routes_changed());
|
||||||
}
|
}
|
||||||
Ok(CompletionsVc::cell(children).completed())
|
Ok(Vc::<Completions>::cell(children).completed())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(transparent)]
|
#[turbo_tasks::value(transparent)]
|
||||||
pub struct OptionAppDir(Option<FileSystemPathVc>);
|
pub struct OptionAppDir(Option<Vc<FileSystemPath>>);
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl OptionAppDirVc {
|
impl OptionAppDir {
|
||||||
/// Returns a completion that changes when any route in the whole tree
|
/// Returns a completion that changes when any route in the whole tree
|
||||||
/// changes.
|
/// changes.
|
||||||
#[turbo_tasks::function]
|
#[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? {
|
if let Some(app_dir) = *self.await? {
|
||||||
let directory_tree = get_directory_tree(app_dir, next_config.page_extensions());
|
let directory_tree = get_directory_tree(app_dir, next_config.page_extensions());
|
||||||
directory_tree.routes_changed().await?;
|
directory_tree.routes_changed().await?;
|
||||||
}
|
}
|
||||||
Ok(CompletionVc::new())
|
Ok(Completion::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds and returns the [DirectoryTree] of the app directory if existing.
|
/// Finds and returns the [DirectoryTree] of the app directory if existing.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn find_app_dir(project_path: FileSystemPathVc) -> Result<OptionAppDirVc> {
|
pub async fn find_app_dir(project_path: Vc<FileSystemPath>) -> Result<Vc<OptionAppDir>> {
|
||||||
let app = project_path.join("app");
|
let app = project_path.join("app".to_string());
|
||||||
let src_app = project_path.join("src/app");
|
let src_app = project_path.join("src/app".to_string());
|
||||||
let app_dir = if *app.get_type().await? == FileSystemEntryType::Directory {
|
let app_dir = if *app.get_type().await? == FileSystemEntryType::Directory {
|
||||||
app
|
app
|
||||||
} else if *src_app.get_type().await? == FileSystemEntryType::Directory {
|
} else if *src_app.get_type().await? == FileSystemEntryType::Directory {
|
||||||
src_app
|
src_app
|
||||||
} else {
|
} else {
|
||||||
return Ok(OptionAppDirVc::cell(None));
|
return Ok(Vc::cell(None));
|
||||||
}
|
}
|
||||||
.resolve()
|
.resolve()
|
||||||
.await?;
|
.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
|
/// Finds and returns the [DirectoryTree] of the app directory if enabled and
|
||||||
/// existing.
|
/// existing.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn find_app_dir_if_enabled(
|
pub async fn find_app_dir_if_enabled(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
) -> Result<OptionAppDirVc> {
|
) -> Result<Vc<OptionAppDir>> {
|
||||||
if !*next_config.app_dir().await? {
|
if !*next_config.app_dir().await? {
|
||||||
return Ok(OptionAppDirVc::cell(None));
|
return Ok(Vc::cell(None));
|
||||||
}
|
}
|
||||||
Ok(find_app_dir(project_path))
|
Ok(find_app_dir(project_path))
|
||||||
}
|
}
|
||||||
|
@ -297,9 +295,9 @@ fn match_metadata_file<'a>(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn get_directory_tree(
|
async fn get_directory_tree(
|
||||||
dir: FileSystemPathVc,
|
dir: Vc<FileSystemPath>,
|
||||||
page_extensions: StringsVc,
|
page_extensions: Vc<Vec<String>>,
|
||||||
) -> Result<DirectoryTreeVc> {
|
) -> Result<Vc<DirectoryTree>> {
|
||||||
let DirectoryContent::Entries(entries) = &*dir.read_dir().await? else {
|
let DirectoryContent::Entries(entries) = &*dir.read_dir().await? else {
|
||||||
bail!("{} must be a directory", dir.to_string().await?);
|
bail!("{} must be a directory", dir.to_string().await?);
|
||||||
};
|
};
|
||||||
|
@ -367,7 +365,7 @@ async fn get_directory_tree(
|
||||||
let basename = file_name
|
let basename = file_name
|
||||||
.rsplit_once('.')
|
.rsplit_once('.')
|
||||||
.map_or(file_name, |(basename, _)| basename);
|
.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 =
|
let alt_path =
|
||||||
matches!(&*alt_path.get_type().await?, FileSystemEntryType::File)
|
matches!(&*alt_path.get_type().await?, FileSystemEntryType::File)
|
||||||
.then_some(alt_path);
|
.then_some(alt_path);
|
||||||
|
@ -416,16 +414,16 @@ async fn get_directory_tree(
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LoaderTree {
|
pub struct LoaderTree {
|
||||||
pub segment: String,
|
pub segment: String,
|
||||||
pub parallel_routes: IndexMap<String, LoaderTreeVc>,
|
pub parallel_routes: IndexMap<String, Vc<LoaderTree>>,
|
||||||
pub components: ComponentsVc,
|
pub components: Vc<Components>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn merge_loader_trees(
|
async fn merge_loader_trees(
|
||||||
app_dir: FileSystemPathVc,
|
app_dir: Vc<FileSystemPath>,
|
||||||
tree1: LoaderTreeVc,
|
tree1: Vc<LoaderTree>,
|
||||||
tree2: LoaderTreeVc,
|
tree2: Vc<LoaderTree>,
|
||||||
) -> Result<LoaderTreeVc> {
|
) -> Result<Vc<LoaderTree>> {
|
||||||
let tree1 = tree1.await?;
|
let tree1 = tree1.await?;
|
||||||
let tree2 = tree2.await?;
|
let tree2 = tree2.await?;
|
||||||
|
|
||||||
|
@ -463,8 +461,8 @@ async fn merge_loader_trees(
|
||||||
TaskInput,
|
TaskInput,
|
||||||
)]
|
)]
|
||||||
pub enum Entrypoint {
|
pub enum Entrypoint {
|
||||||
AppPage { loader_tree: LoaderTreeVc },
|
AppPage { loader_tree: Vc<LoaderTree> },
|
||||||
AppRoute { path: FileSystemPathVc },
|
AppRoute { path: Vc<FileSystemPath> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(transparent)]
|
#[turbo_tasks::value(transparent)]
|
||||||
|
@ -479,10 +477,10 @@ fn match_parallel_route(name: &str) -> Option<&str> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_parallel_route(
|
async fn add_parallel_route(
|
||||||
app_dir: FileSystemPathVc,
|
app_dir: Vc<FileSystemPath>,
|
||||||
result: &mut IndexMap<String, LoaderTreeVc>,
|
result: &mut IndexMap<String, Vc<LoaderTree>>,
|
||||||
key: String,
|
key: String,
|
||||||
loader_tree: LoaderTreeVc,
|
loader_tree: Vc<LoaderTree>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match result.entry(key) {
|
match result.entry(key) {
|
||||||
Entry::Occupied(mut e) => {
|
Entry::Occupied(mut e) => {
|
||||||
|
@ -499,10 +497,10 @@ async fn add_parallel_route(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_app_page(
|
async fn add_app_page(
|
||||||
app_dir: FileSystemPathVc,
|
app_dir: Vc<FileSystemPath>,
|
||||||
result: &mut IndexMap<String, Entrypoint>,
|
result: &mut IndexMap<String, Entrypoint>,
|
||||||
key: String,
|
key: String,
|
||||||
loader_tree: LoaderTreeVc,
|
loader_tree: Vc<LoaderTree>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match result.entry(key) {
|
match result.entry(key) {
|
||||||
Entry::Occupied(mut e) => {
|
Entry::Occupied(mut e) => {
|
||||||
|
@ -510,11 +508,10 @@ async fn add_app_page(
|
||||||
let Entrypoint::AppPage { loader_tree: value } = value else {
|
let Entrypoint::AppPage { loader_tree: value } = value else {
|
||||||
DirectoryTreeIssue {
|
DirectoryTreeIssue {
|
||||||
app_dir,
|
app_dir,
|
||||||
message: StringVc::cell(format!("Conflicting route at {}", e.key())),
|
message: Vc::cell(format!("Conflicting route at {}", e.key())),
|
||||||
severity: IssueSeverity::Error.cell(),
|
severity: IssueSeverity::Error.cell(),
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
.as_issue()
|
|
||||||
.emit();
|
.emit();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
@ -530,20 +527,19 @@ async fn add_app_page(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_app_route(
|
async fn add_app_route(
|
||||||
app_dir: FileSystemPathVc,
|
app_dir: Vc<FileSystemPath>,
|
||||||
result: &mut IndexMap<String, Entrypoint>,
|
result: &mut IndexMap<String, Entrypoint>,
|
||||||
key: String,
|
key: String,
|
||||||
path: FileSystemPathVc,
|
path: Vc<FileSystemPath>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match result.entry(key) {
|
match result.entry(key) {
|
||||||
Entry::Occupied(mut e) => {
|
Entry::Occupied(mut e) => {
|
||||||
DirectoryTreeIssue {
|
DirectoryTreeIssue {
|
||||||
app_dir,
|
app_dir,
|
||||||
message: StringVc::cell(format!("Conflicting route at {}", e.key())),
|
message: Vc::cell(format!("Conflicting route at {}", e.key())),
|
||||||
severity: IssueSeverity::Error.cell(),
|
severity: IssueSeverity::Error.cell(),
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
.as_issue()
|
|
||||||
.emit();
|
.emit();
|
||||||
*e.get_mut() = Entrypoint::AppRoute { path };
|
*e.get_mut() = Entrypoint::AppRoute { path };
|
||||||
}
|
}
|
||||||
|
@ -555,25 +551,28 @@ async fn add_app_route(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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))
|
directory_tree_to_entrypoints(app_dir, get_directory_tree(app_dir, page_extensions))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn directory_tree_to_entrypoints(
|
fn directory_tree_to_entrypoints(
|
||||||
app_dir: FileSystemPathVc,
|
app_dir: Vc<FileSystemPath>,
|
||||||
directory_tree: DirectoryTreeVc,
|
directory_tree: Vc<DirectoryTree>,
|
||||||
) -> EntrypointsVc {
|
) -> Vc<Entrypoints> {
|
||||||
directory_tree_to_entrypoints_internal(app_dir, "", directory_tree, "/")
|
directory_tree_to_entrypoints_internal(app_dir, "".to_string(), directory_tree, "/".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn directory_tree_to_entrypoints_internal(
|
async fn directory_tree_to_entrypoints_internal(
|
||||||
app_dir: FileSystemPathVc,
|
app_dir: Vc<FileSystemPath>,
|
||||||
directory_name: &str,
|
directory_name: String,
|
||||||
directory_tree: DirectoryTreeVc,
|
directory_tree: Vc<DirectoryTree>,
|
||||||
path_prefix: &str,
|
path_prefix: String,
|
||||||
) -> Result<EntrypointsVc> {
|
) -> Result<Vc<Entrypoints>> {
|
||||||
let mut result = IndexMap::new();
|
let mut result = IndexMap::new();
|
||||||
|
|
||||||
let directory_tree = &*directory_tree.await?;
|
let directory_tree = &*directory_tree.await?;
|
||||||
|
@ -581,7 +580,7 @@ async fn directory_tree_to_entrypoints_internal(
|
||||||
let subdirectories = &directory_tree.subdirectories;
|
let subdirectories = &directory_tree.subdirectories;
|
||||||
let components = directory_tree.components.await?;
|
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 {
|
if let Some(page) = components.page {
|
||||||
add_app_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 parallel_route_key = match_parallel_route(subdir_name);
|
||||||
let map = directory_tree_to_entrypoints_internal(
|
let map = directory_tree_to_entrypoints_internal(
|
||||||
app_dir,
|
app_dir,
|
||||||
subdir_name,
|
subdir_name.to_string(),
|
||||||
subdirectory,
|
subdirectory,
|
||||||
// TODO(alexkirsz) We don't check optional segment here because Next.js seems to expect
|
// 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".
|
// it, although this might just need to be computed as "original name".
|
||||||
if parallel_route_key.is_some() {
|
if parallel_route_key.is_some() {
|
||||||
Cow::Borrowed(path_prefix)
|
path_prefix.clone()
|
||||||
} else if path_prefix == "/" {
|
} else if path_prefix == "/" {
|
||||||
format!("/{subdir_name}").into()
|
format!("/{subdir_name}")
|
||||||
} else {
|
} else {
|
||||||
format!("{path_prefix}/{subdir_name}").into()
|
format!("{path_prefix}/{subdir_name}")
|
||||||
}
|
},
|
||||||
.as_ref(),
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
for (full_path, &entrypoint) in map.iter() {
|
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
|
/// 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.
|
/// Returns the global metadata for an app directory.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_global_metadata(
|
pub async fn get_global_metadata(
|
||||||
app_dir: FileSystemPathVc,
|
app_dir: Vc<FileSystemPath>,
|
||||||
page_extensions: StringsVc,
|
page_extensions: Vc<Vec<String>>,
|
||||||
) -> Result<GlobalMetadataVc> {
|
) -> Result<Vc<GlobalMetadata>> {
|
||||||
let DirectoryContent::Entries(entries) = &*app_dir.read_dir().await? else {
|
let DirectoryContent::Entries(entries) = &*app_dir.read_dir().await? else {
|
||||||
bail!("app_dir must be a directory")
|
bail!("app_dir must be a directory")
|
||||||
};
|
};
|
||||||
|
@ -778,37 +776,37 @@ pub async fn get_global_metadata(
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
struct DirectoryTreeIssue {
|
struct DirectoryTreeIssue {
|
||||||
pub severity: IssueSeverityVc,
|
pub severity: Vc<IssueSeverity>,
|
||||||
pub app_dir: FileSystemPathVc,
|
pub app_dir: Vc<FileSystemPath>,
|
||||||
pub message: StringVc,
|
pub message: Vc<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Issue for DirectoryTreeIssue {
|
impl Issue for DirectoryTreeIssue {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn severity(&self) -> IssueSeverityVc {
|
fn severity(&self) -> Vc<IssueSeverity> {
|
||||||
self.severity
|
self.severity
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn title(&self) -> Result<StringVc> {
|
async fn title(&self) -> Result<Vc<String>> {
|
||||||
Ok(StringVc::cell(
|
Ok(Vc::cell(
|
||||||
"An issue occurred while preparing your Next.js app".to_string(),
|
"An issue occurred while preparing your Next.js app".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn category(&self) -> StringVc {
|
fn category(&self) -> Vc<String> {
|
||||||
StringVc::cell("next app".to_string())
|
Vc::cell("next app".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn context(&self) -> FileSystemPathVc {
|
fn context(&self) -> Vc<FileSystemPath> {
|
||||||
self.app_dir
|
self.app_dir
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn description(&self) -> StringVc {
|
fn description(&self) -> Vc<String> {
|
||||||
self.message
|
self.message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{Value, Vc};
|
||||||
primitives::{BoolVc, StringVc},
|
|
||||||
Value,
|
|
||||||
};
|
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::{FileSystemEntryType, FileSystemPathVc},
|
turbo::tasks_fs::{FileSystemEntryType, FileSystemPath},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc},
|
issue::{Issue, IssueExt, IssueSeverity},
|
||||||
resolve::{parse::RequestVc, pattern::Pattern, resolve},
|
resolve::{parse::Request, pattern::Pattern, resolve},
|
||||||
},
|
},
|
||||||
node::transforms::webpack::{WebpackLoaderItem, WebpackLoaderItemsVc},
|
node::transforms::webpack::WebpackLoaderItem,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
module_options::{LoaderRuleItem, OptionWebpackRulesVc, WebpackRulesVc},
|
module_options::{LoaderRuleItem, OptionWebpackRules, WebpackRules},
|
||||||
resolve_options,
|
resolve_options,
|
||||||
resolve_options_context::ResolveOptionsContext,
|
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.
|
/// webpack loader for each eligible file type if it doesn't already exist.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn maybe_add_babel_loader(
|
pub async fn maybe_add_babel_loader(
|
||||||
project_root: FileSystemPathVc,
|
project_root: Vc<FileSystemPath>,
|
||||||
webpack_rules: Option<WebpackRulesVc>,
|
webpack_rules: Option<Vc<WebpackRules>>,
|
||||||
) -> Result<OptionWebpackRulesVc> {
|
) -> Result<Vc<OptionWebpackRules>> {
|
||||||
let has_babel_config = {
|
let has_babel_config = {
|
||||||
let mut has_babel_config = false;
|
let mut has_babel_config = false;
|
||||||
for filename in BABEL_CONFIG_FILES {
|
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) {
|
if matches!(filetype, FileSystemEntryType::File) {
|
||||||
has_babel_config = true;
|
has_babel_config = true;
|
||||||
break;
|
break;
|
||||||
|
@ -76,18 +73,17 @@ pub async fn maybe_add_babel_loader(
|
||||||
{
|
{
|
||||||
BabelIssue {
|
BabelIssue {
|
||||||
path: project_root,
|
path: project_root,
|
||||||
title: StringVc::cell(
|
title: Vc::cell(
|
||||||
"Unable to resolve babel-loader, but a babel config is present"
|
"Unable to resolve babel-loader, but a babel config is present"
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
),
|
),
|
||||||
description: StringVc::cell(
|
description: Vc::cell(
|
||||||
"Make sure babel-loader is installed via your package manager."
|
"Make sure babel-loader is installed via your package manager."
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
),
|
),
|
||||||
severity: IssueSeverity::Fatal.cell(),
|
severity: IssueSeverity::Fatal.cell(),
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
.as_issue()
|
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
has_emitted_babel_resolve_issue = true;
|
has_emitted_babel_resolve_issue = true;
|
||||||
|
@ -100,12 +96,12 @@ pub async fn maybe_add_babel_loader(
|
||||||
if let Some(rule) = rule {
|
if let Some(rule) = rule {
|
||||||
let mut loaders = rule.loaders.await?.clone_value();
|
let mut loaders = rule.loaders.await?.clone_value();
|
||||||
loaders.push(loader);
|
loaders.push(loader);
|
||||||
rule.loaders = WebpackLoaderItemsVc::cell(loaders);
|
rule.loaders = Vc::cell(loaders);
|
||||||
} else {
|
} else {
|
||||||
rules.insert(
|
rules.insert(
|
||||||
pattern.to_string(),
|
pattern.to_string(),
|
||||||
LoaderRuleItem {
|
LoaderRuleItem {
|
||||||
loaders: WebpackLoaderItemsVc::cell(vec![loader]),
|
loaders: Vc::cell(vec![loader]),
|
||||||
rename_as: Some("*".to_string()),
|
rename_as: Some("*".to_string()),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -115,19 +111,17 @@ pub async fn maybe_add_babel_loader(
|
||||||
}
|
}
|
||||||
|
|
||||||
if has_changed {
|
if has_changed {
|
||||||
return Ok(OptionWebpackRulesVc::cell(Some(WebpackRulesVc::cell(
|
return Ok(Vc::cell(Some(Vc::cell(rules))));
|
||||||
rules,
|
|
||||||
))));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(OptionWebpackRulesVc::cell(webpack_rules))
|
Ok(Vc::cell(webpack_rules))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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(
|
let result = resolve(
|
||||||
project_path,
|
project_path,
|
||||||
RequestVc::parse(Value::new(Pattern::Constant(
|
Request::parse(Value::new(Pattern::Constant(
|
||||||
"babel-loader/package.json".to_string(),
|
"babel-loader/package.json".to_string(),
|
||||||
))),
|
))),
|
||||||
resolve_options(
|
resolve_options(
|
||||||
|
@ -142,41 +136,41 @@ pub async fn is_babel_loader_available(project_path: FileSystemPathVc) -> Result
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
let assets = result.primary_assets().await?;
|
let assets = result.primary_assets().await?;
|
||||||
Ok(BoolVc::cell(!assets.is_empty()))
|
Ok(Vc::cell(!assets.is_empty()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct BabelIssue {
|
struct BabelIssue {
|
||||||
path: FileSystemPathVc,
|
path: Vc<FileSystemPath>,
|
||||||
title: StringVc,
|
title: Vc<String>,
|
||||||
description: StringVc,
|
description: Vc<String>,
|
||||||
severity: IssueSeverityVc,
|
severity: Vc<IssueSeverity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Issue for BabelIssue {
|
impl Issue for BabelIssue {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn category(&self) -> StringVc {
|
fn category(&self) -> Vc<String> {
|
||||||
StringVc::cell("other".to_string())
|
Vc::cell("other".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn severity(&self) -> IssueSeverityVc {
|
fn severity(&self) -> Vc<IssueSeverity> {
|
||||||
self.severity
|
self.severity
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn context(&self) -> FileSystemPathVc {
|
fn context(&self) -> Vc<FileSystemPath> {
|
||||||
self.path
|
self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn title(&self) -> StringVc {
|
fn title(&self) -> Vc<String> {
|
||||||
self.title
|
self.title
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn description(&self) -> StringVc {
|
fn description(&self) -> Vc<String> {
|
||||||
self.description
|
self.description
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +1,47 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use indexmap::{indexmap, IndexMap};
|
use indexmap::{indexmap, IndexMap};
|
||||||
use turbo_tasks::{Value, ValueToString};
|
use turbo_tasks::{Value, ValueToString, Vc};
|
||||||
use turbo_tasks_fs::{File, FileSystemPathVc};
|
use turbo_tasks_fs::{File, FileSystemPath};
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
chunk::EvaluatableAssetVc,
|
chunk::EvaluatableAsset,
|
||||||
context::{AssetContext, AssetContextVc},
|
context::AssetContext,
|
||||||
issue::{IssueSeverity, OptionIssueSourceVc},
|
issue::{IssueSeverity, OptionIssueSource},
|
||||||
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssetsVc, ReferenceType},
|
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssets, ReferenceType},
|
||||||
resolve::parse::RequestVc,
|
resolve::parse::Request,
|
||||||
source::SourceVc,
|
source::Source,
|
||||||
virtual_source::VirtualSourceVc,
|
virtual_source::VirtualSource,
|
||||||
},
|
},
|
||||||
ecmascript::{resolve::esm_resolve, utils::StringifyJs, EcmascriptModuleAssetVc},
|
ecmascript::{resolve::esm_resolve, utils::StringifyJs, EcmascriptModuleAsset},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn route_bootstrap(
|
pub async fn route_bootstrap(
|
||||||
asset: AssetVc,
|
asset: Vc<Box<dyn Asset>>,
|
||||||
context: AssetContextVc,
|
context: Vc<Box<dyn AssetContext>>,
|
||||||
base_path: FileSystemPathVc,
|
base_path: Vc<FileSystemPath>,
|
||||||
bootstrap_asset: SourceVc,
|
bootstrap_asset: Vc<Box<dyn Source>>,
|
||||||
config: BootstrapConfigVc,
|
config: Vc<BootstrapConfig>,
|
||||||
) -> Result<EvaluatableAssetVc> {
|
) -> Result<Vc<Box<dyn EvaluatableAsset>>> {
|
||||||
let resolve_origin = if let Some(m) = EcmascriptModuleAssetVc::resolve_from(asset).await? {
|
let resolve_origin =
|
||||||
m.as_resolve_origin()
|
if let Some(m) = Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(asset).await? {
|
||||||
} else {
|
Vc::upcast(m)
|
||||||
bail!("asset does not represent an ecmascript module");
|
} else {
|
||||||
};
|
bail!("asset does not represent an ecmascript module");
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: this is where you'd switch the route kind to the one you need
|
// TODO: this is where you'd switch the route kind to the one you need
|
||||||
let route_module_kind = "app-route";
|
let route_module_kind = "app-route";
|
||||||
|
|
||||||
let resolved_route_module_asset = esm_resolve(
|
let resolved_route_module_asset = esm_resolve(
|
||||||
resolve_origin,
|
resolve_origin,
|
||||||
RequestVc::parse_string(format!(
|
Request::parse_string(format!(
|
||||||
"next/dist/server/future/route-modules/{}/module",
|
"next/dist/server/future/route-modules/{}/module",
|
||||||
route_module_kind
|
route_module_kind
|
||||||
)),
|
)),
|
||||||
Value::new(EcmaScriptModulesReferenceSubType::Undefined),
|
Value::new(EcmaScriptModulesReferenceSubType::Undefined),
|
||||||
OptionIssueSourceVc::none(),
|
OptionIssueSource::none(),
|
||||||
IssueSeverity::Error.cell(),
|
IssueSeverity::Error.cell(),
|
||||||
);
|
);
|
||||||
let route_module_asset = match &*resolved_route_module_asset.first_asset().await? {
|
let route_module_asset = match &*resolved_route_module_asset.first_asset().await? {
|
||||||
|
@ -53,7 +54,7 @@ pub async fn route_bootstrap(
|
||||||
context,
|
context,
|
||||||
base_path,
|
base_path,
|
||||||
bootstrap_asset,
|
bootstrap_asset,
|
||||||
InnerAssetsVc::cell(indexmap! {
|
Vc::cell(indexmap! {
|
||||||
"ROUTE_MODULE".to_string() => route_module_asset,
|
"ROUTE_MODULE".to_string() => route_module_asset,
|
||||||
}),
|
}),
|
||||||
config,
|
config,
|
||||||
|
@ -64,22 +65,22 @@ pub async fn route_bootstrap(
|
||||||
pub struct BootstrapConfig(IndexMap<String, String>);
|
pub struct BootstrapConfig(IndexMap<String, String>);
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl BootstrapConfigVc {
|
impl BootstrapConfig {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Vc<Self> {
|
||||||
BootstrapConfigVc::cell(IndexMap::new())
|
Vc::cell(IndexMap::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn bootstrap(
|
pub async fn bootstrap(
|
||||||
asset: AssetVc,
|
asset: Vc<Box<dyn Asset>>,
|
||||||
context: AssetContextVc,
|
context: Vc<Box<dyn AssetContext>>,
|
||||||
base_path: FileSystemPathVc,
|
base_path: Vc<FileSystemPath>,
|
||||||
bootstrap_asset: SourceVc,
|
bootstrap_asset: Vc<Box<dyn Source>>,
|
||||||
inner_assets: InnerAssetsVc,
|
inner_assets: Vc<InnerAssets>,
|
||||||
config: BootstrapConfigVc,
|
config: Vc<BootstrapConfig>,
|
||||||
) -> Result<EvaluatableAssetVc> {
|
) -> Result<Vc<Box<dyn EvaluatableAsset>>> {
|
||||||
let path = asset.ident().path().await?;
|
let path = asset.ident().path().await?;
|
||||||
let Some(path) = base_path.await?.get_path_to(&path) else {
|
let Some(path) = base_path.await?.get_path_to(&path) else {
|
||||||
bail!(
|
bail!(
|
||||||
|
@ -106,31 +107,32 @@ pub async fn bootstrap(
|
||||||
config.insert("KIND".to_string(), "APP_ROUTE".to_string());
|
config.insert("KIND".to_string(), "APP_ROUTE".to_string());
|
||||||
|
|
||||||
let config_asset = context.process(
|
let config_asset = context.process(
|
||||||
VirtualSourceVc::new(
|
Vc::upcast(VirtualSource::new(
|
||||||
asset.ident().path().join("bootstrap-config.ts"),
|
asset.ident().path().join("bootstrap-config.ts".to_string()),
|
||||||
File::from(
|
AssetContent::file(
|
||||||
config
|
File::from(
|
||||||
.iter()
|
config
|
||||||
.map(|(k, v)| format!("export const {} = {};\n", k, StringifyJs(v)))
|
.iter()
|
||||||
.collect::<Vec<_>>()
|
.map(|(k, v)| format!("export const {} = {};\n", k, StringifyJs(v)))
|
||||||
.join(""),
|
.collect::<Vec<_>>()
|
||||||
)
|
.join(""),
|
||||||
.into(),
|
)
|
||||||
)
|
.into(),
|
||||||
.into(),
|
),
|
||||||
Value::new(ReferenceType::Internal(InnerAssetsVc::empty())),
|
)),
|
||||||
|
Value::new(ReferenceType::Internal(InnerAssets::empty())),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut inner_assets = inner_assets.await?.clone_value();
|
let mut inner_assets = inner_assets.await?.clone_value();
|
||||||
inner_assets.insert("ENTRY".to_string(), asset);
|
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(
|
let asset = context.process(
|
||||||
bootstrap_asset,
|
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");
|
bail!("internal module must be evaluatable");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,28 @@
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::{FileContentVc, FileSystem, FileSystemPathVc, FileSystemVc},
|
turbo::tasks_fs::{FileContent, FileSystem, FileSystemPath},
|
||||||
turbopack::core::{file_source::FileSourceVc, source::SourceVc},
|
turbopack::core::{file_source::FileSource, source::Source},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const VIRTUAL_PACKAGE_NAME: &str = "@vercel/turbopack-next";
|
pub const VIRTUAL_PACKAGE_NAME: &str = "@vercel/turbopack-next";
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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
|
// [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_fs::embed_directory!("next", "$CARGO_MANIFEST_DIR/js/src")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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()
|
next_js_fs().root().join(path).read()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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)
|
next_js_fs().root().join(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(crate) fn next_asset(path: &str) -> SourceVc {
|
pub(crate) fn next_asset(path: String) -> Vc<Box<dyn Source>> {
|
||||||
FileSourceVc::new(next_js_file_path(path)).into()
|
Vc::upcast(FileSource::new(next_js_file_path(path)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{
|
||||||
graph::{AdjacencyMap, GraphTraversal},
|
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::{
|
use turbopack_binding::turbopack::core::{
|
||||||
asset::Asset,
|
asset::Asset,
|
||||||
output::{OutputAssetVc, OutputAssetsVc},
|
output::{OutputAsset, OutputAssets},
|
||||||
reference::AssetReference,
|
reference::AssetReference,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,31 +14,36 @@ use turbopack_binding::turbopack::core::{
|
||||||
/// inside the node root or the client root.
|
/// inside the node root or the client root.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn emit_all_assets(
|
pub async fn emit_all_assets(
|
||||||
assets: OutputAssetsVc,
|
assets: Vc<OutputAssets>,
|
||||||
node_root: FileSystemPathVc,
|
node_root: Vc<FileSystemPath>,
|
||||||
client_relative_path: FileSystemPathVc,
|
client_relative_path: Vc<FileSystemPath>,
|
||||||
client_output_path: FileSystemPathVc,
|
client_output_path: Vc<FileSystemPath>,
|
||||||
) -> Result<CompletionVc> {
|
) -> Result<Vc<Completion>> {
|
||||||
let all_assets = all_assets_from_entries(assets).await?;
|
let all_assets = all_assets_from_entries(assets).await?;
|
||||||
Ok(CompletionsVc::all(
|
Ok(Completions::all(
|
||||||
all_assets
|
all_assets
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.map(|asset| async move {
|
.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));
|
return Ok(emit(asset));
|
||||||
} else if asset
|
} else if asset
|
||||||
.ident()
|
.ident()
|
||||||
.path()
|
.path()
|
||||||
.await?
|
.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
|
// Client assets are emitted to the client output path, which is prefixed with
|
||||||
// _next. We need to rebase them to remove that prefix.
|
// _next. We need to rebase them to remove that prefix.
|
||||||
return Ok(emit_rebase(asset, client_relative_path, client_output_path));
|
return Ok(emit_rebase(asset, client_relative_path, client_output_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(CompletionVc::immutable())
|
Ok(Completion::immutable())
|
||||||
})
|
})
|
||||||
.try_join()
|
.try_join()
|
||||||
.await?,
|
.await?,
|
||||||
|
@ -46,12 +51,16 @@ pub async fn emit_all_assets(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn emit(asset: OutputAssetVc) -> CompletionVc {
|
fn emit(asset: Vc<Box<dyn OutputAsset>>) -> Vc<Completion> {
|
||||||
asset.content().write(asset.ident().path())
|
asset.content().write(asset.ident().path())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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
|
asset
|
||||||
.content()
|
.content()
|
||||||
.write(rebase(asset.ident().path(), from, to))
|
.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
|
/// Walks the asset graph from multiple assets and collect all referenced
|
||||||
/// assets.
|
/// assets.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn all_assets_from_entries(entries: OutputAssetsVc) -> Result<OutputAssetsVc> {
|
async fn all_assets_from_entries(entries: Vc<OutputAssets>) -> Result<Vc<OutputAssets>> {
|
||||||
Ok(OutputAssetsVc::cell(
|
Ok(Vc::cell(
|
||||||
AdjacencyMap::new()
|
AdjacencyMap::new()
|
||||||
.skip_duplicates()
|
.skip_duplicates()
|
||||||
.visit(entries.await?.iter().copied(), get_referenced_assets)
|
.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.
|
/// Computes the list of all chunk children of a given chunk.
|
||||||
async fn get_referenced_assets(
|
async fn get_referenced_assets(
|
||||||
asset: OutputAssetVc,
|
asset: Vc<Box<dyn OutputAsset>>,
|
||||||
) -> Result<impl Iterator<Item = OutputAssetVc> + Send> {
|
) -> Result<impl Iterator<Item = Vc<Box<dyn OutputAsset>>> + Send> {
|
||||||
Ok(asset
|
Ok(
|
||||||
.references()
|
asset
|
||||||
.await?
|
.references()
|
||||||
.iter()
|
.await?
|
||||||
.map(|reference| async move {
|
.iter()
|
||||||
let primary_assets = reference.resolve_reference().primary_assets().await?;
|
.map(|reference| async move {
|
||||||
Ok(primary_assets.clone_value())
|
let primary_assets = reference.resolve_reference().primary_assets().await?;
|
||||||
})
|
Ok(primary_assets.clone_value())
|
||||||
.try_join()
|
})
|
||||||
.await?
|
.try_join()
|
||||||
.into_iter()
|
.await?
|
||||||
.flatten()
|
.into_iter()
|
||||||
.map(|asset| async move { Ok(OutputAssetVc::resolve_from(asset).await?) })
|
.flatten()
|
||||||
.try_join()
|
.map(|asset| async move {
|
||||||
.await?
|
Ok(Vc::try_resolve_sidecast::<Box<dyn OutputAsset>>(asset).await?)
|
||||||
.into_iter()
|
})
|
||||||
.flatten())
|
.try_join()
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.flatten(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +1,47 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use indexmap::indexmap;
|
use indexmap::indexmap;
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_env::{
|
turbo::tasks_env::{CustomProcessEnv, EnvMap, FilterProcessEnv, ProcessEnv},
|
||||||
CustomProcessEnvVc, EnvMapVc, FilterProcessEnvVc, ProcessEnv, ProcessEnvVc,
|
turbopack::env::EmbeddableProcessEnv,
|
||||||
},
|
|
||||||
turbopack::env::EmbeddableProcessEnvVc,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::next_config::NextConfigVc;
|
use crate::next_config::NextConfig;
|
||||||
|
|
||||||
/// Creates a ProcessEnvVc safe to use in JS, by stringifying and encoding as
|
/// Creates a Vc<Box<dyn ProcessEnv>> safe to use in JS, by stringifying and
|
||||||
/// regular JS strings. Setting `client` to true will additionally filter the
|
/// encoding as regular JS strings. Setting `client` to true will additionally
|
||||||
/// env to just the keys that are acceptable for the client to access.
|
/// 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
|
/// For now, it also injects overridden values as if they were real JS code, eg
|
||||||
/// an Object and not a String.
|
/// an Object and not a String.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn env_for_js(
|
pub async fn env_for_js(
|
||||||
env: ProcessEnvVc,
|
env: Vc<Box<dyn ProcessEnv>>,
|
||||||
client: bool,
|
client: bool,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
) -> Result<ProcessEnvVc> {
|
) -> Result<Vc<Box<dyn ProcessEnv>>> {
|
||||||
let test_mode = env.read("__NEXT_TEST_MODE").await?;
|
let test_mode = env.read("__NEXT_TEST_MODE".to_string()).await?;
|
||||||
let test_mode = test_mode.as_deref().unwrap_or("");
|
let test_mode = test_mode.as_deref().unwrap_or("");
|
||||||
|
|
||||||
let env = if client {
|
let env = if client {
|
||||||
FilterProcessEnvVc::new(
|
Vc::upcast(FilterProcessEnv::new(
|
||||||
env,
|
env,
|
||||||
vec![
|
vec![
|
||||||
"NEXT_PUBLIC_".to_string(),
|
"NEXT_PUBLIC_".to_string(),
|
||||||
"NODE_ENV".to_string(),
|
"NODE_ENV".to_string(),
|
||||||
"PORT".to_string(),
|
"PORT".to_string(),
|
||||||
],
|
],
|
||||||
)
|
))
|
||||||
.into()
|
|
||||||
} else {
|
} else {
|
||||||
// Server doesn't need to have env vars injected since it will have them in the
|
// Server doesn't need to have env vars injected since it will have them in the
|
||||||
// real process.env.
|
// real process.env.
|
||||||
EnvMapVc::cell(Default::default()).into()
|
Vc::upcast(EnvMap::empty())
|
||||||
};
|
};
|
||||||
|
|
||||||
let env =
|
let env = Vc::upcast(EmbeddableProcessEnv::new(Vc::upcast(
|
||||||
EmbeddableProcessEnvVc::new(CustomProcessEnvVc::new(env, next_config.env()).into()).into();
|
CustomProcessEnv::new(env, next_config.env()),
|
||||||
|
)));
|
||||||
|
|
||||||
let image_config = next_config.image_config().await?;
|
let image_config = next_config.image_config().await?;
|
||||||
let mut map = indexmap! {
|
let mut map = indexmap! {
|
||||||
|
@ -65,5 +65,5 @@ pub async fn env_for_js(
|
||||||
map.insert("__NEXT_TEST_MODE".to_string(), "true".to_string());
|
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 std::collections::HashMap;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use turbo_tasks::Value;
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{tasks_env::ProcessEnvVc, tasks_fs::FileSystemPathVc},
|
turbo::{tasks_env::ProcessEnv, tasks_fs::FileSystemPath},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
compile_time_info::CompileTimeInfoVc,
|
compile_time_info::CompileTimeInfo,
|
||||||
context::AssetContextVc,
|
context::AssetContext,
|
||||||
resolve::{options::ImportMap, origin::PlainResolveOriginVc},
|
resolve::{options::ImportMap, origin::PlainResolveOrigin},
|
||||||
},
|
|
||||||
dev_server::html::DevHtmlAssetVc,
|
|
||||||
node::execution_context::ExecutionContextVc,
|
|
||||||
turbopack::{
|
|
||||||
ecmascript::EcmascriptModuleAssetVc, transition::TransitionsByNameVc,
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
|
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_chunking_context, get_client_module_options_context,
|
||||||
get_client_resolve_options_context, get_client_runtime_entries, ClientContextType,
|
get_client_resolve_options_context, get_client_runtime_entries, ClientContextType,
|
||||||
},
|
},
|
||||||
next_config::NextConfigVc,
|
next_config::NextConfig,
|
||||||
next_import_map::insert_next_shared_aliases,
|
next_import_map::insert_next_shared_aliases,
|
||||||
runtime::resolve_runtime_request,
|
runtime::resolve_runtime_request,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_fallback_page(
|
pub async fn get_fallback_page(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
dev_server_root: FileSystemPathVc,
|
dev_server_root: Vc<FileSystemPath>,
|
||||||
env: ProcessEnvVc,
|
env: Vc<Box<dyn ProcessEnv>>,
|
||||||
client_compile_time_info: CompileTimeInfoVc,
|
client_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
) -> Result<DevHtmlAssetVc> {
|
) -> Result<Vc<DevHtmlAsset>> {
|
||||||
let ty = Value::new(ClientContextType::Fallback);
|
let ty = Value::new(ClientContextType::Fallback);
|
||||||
let mode = NextMode::Development;
|
let mode = NextMode::Development;
|
||||||
let resolve_options_context =
|
let resolve_options_context =
|
||||||
|
@ -69,35 +66,34 @@ pub async fn get_fallback_page(
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let context: AssetContextVc = ModuleAssetContextVc::new(
|
let context: Vc<Box<dyn AssetContext>> = Vc::upcast(ModuleAssetContext::new(
|
||||||
TransitionsByNameVc::cell(HashMap::new()),
|
Vc::cell(HashMap::new()),
|
||||||
client_compile_time_info,
|
client_compile_time_info,
|
||||||
module_options_context,
|
module_options_context,
|
||||||
resolve_options_context.with_extended_import_map(import_map.cell()),
|
resolve_options_context.with_extended_import_map(import_map.cell()),
|
||||||
)
|
));
|
||||||
.into();
|
|
||||||
|
|
||||||
let runtime_entries = entries.resolve_entries(context);
|
let runtime_entries = entries.resolve_entries(context);
|
||||||
|
|
||||||
let fallback_chunk = resolve_runtime_request(
|
let fallback_chunk = resolve_runtime_request(
|
||||||
PlainResolveOriginVc::new(context, project_path).into(),
|
Vc::upcast(PlainResolveOrigin::new(context, project_path)),
|
||||||
"entry/fallback",
|
"entry/fallback".to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let module = if let Some(module) =
|
let module = if let Some(module) =
|
||||||
EcmascriptModuleAssetVc::resolve_from(fallback_chunk.as_asset()).await?
|
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(fallback_chunk).await?
|
||||||
{
|
{
|
||||||
module
|
module
|
||||||
} else {
|
} else {
|
||||||
bail!("fallback runtime entry is not an ecmascript module");
|
bail!("fallback runtime entry is not an ecmascript module");
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(DevHtmlAssetVc::new(
|
Ok(DevHtmlAsset::new(
|
||||||
dev_server_root.join("fallback.html"),
|
dev_server_root.join("fallback.html".to_string()),
|
||||||
vec![(
|
vec![(
|
||||||
module.into(),
|
Vc::upcast(module),
|
||||||
chunking_context.into(),
|
Vc::upcast(chunking_context),
|
||||||
Some(runtime_entries.with_entry(module.into())),
|
Some(runtime_entries.with_entry(Vc::upcast(module))),
|
||||||
)],
|
)],
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#![feature(async_closure)]
|
#![feature(async_closure)]
|
||||||
#![feature(str_split_remainder)]
|
#![feature(str_split_remainder)]
|
||||||
#![feature(impl_trait_in_assoc_type)]
|
#![feature(impl_trait_in_assoc_type)]
|
||||||
|
#![feature(arbitrary_self_types)]
|
||||||
|
#![feature(async_fn_in_trait)]
|
||||||
|
|
||||||
mod app_render;
|
mod app_render;
|
||||||
mod app_segment_config;
|
mod app_segment_config;
|
||||||
|
@ -47,9 +49,7 @@ mod web_entry_source;
|
||||||
|
|
||||||
pub use app_source::create_app_source;
|
pub use app_source::create_app_source;
|
||||||
pub use emit::emit_all_assets;
|
pub use emit::emit_all_assets;
|
||||||
pub use next_app::unsupported_dynamic_metadata_issue::{
|
pub use next_app::unsupported_dynamic_metadata_issue::UnsupportedDynamicMetadataIssue;
|
||||||
UnsupportedDynamicMetadataIssue, UnsupportedDynamicMetadataIssueVc,
|
|
||||||
};
|
|
||||||
pub use page_loader::create_page_loader_entry_module;
|
pub use page_loader::create_page_loader_entry_module;
|
||||||
pub use page_source::create_page_source;
|
pub use page_source::create_page_source;
|
||||||
pub use turbopack_binding::{turbopack::node::source_map, *};
|
pub use turbopack_binding::{turbopack::node::source_map, *};
|
||||||
|
|
|
@ -2,46 +2,41 @@ use anyhow::Result;
|
||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
use turbo_tasks::{Value, ValueToString};
|
use turbo_tasks::{Value, ValueToString, Vc};
|
||||||
use turbo_tasks_fs::FileSystemPathVc;
|
use turbo_tasks_fs::FileSystemPath;
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::AssetVc,
|
asset::Asset,
|
||||||
context::AssetContext,
|
context::AssetContext,
|
||||||
file_source::FileSourceVc,
|
file_source::FileSource,
|
||||||
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssetsVc, ReferenceType},
|
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssets, ReferenceType},
|
||||||
},
|
|
||||||
ecmascript::{magic_identifier, text::TextContentFileSourceVc, utils::StringifyJs},
|
|
||||||
r#static::StaticModuleAssetVc,
|
|
||||||
turbopack::{
|
|
||||||
transition::{Transition, TransitionVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
|
ecmascript::{magic_identifier, text::TextContentFileSource, utils::StringifyJs},
|
||||||
|
r#static::StaticModuleAsset,
|
||||||
|
turbopack::{transition::Transition, ModuleAssetContext},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app_structure::{
|
app_structure::{Components, LoaderTree, Metadata, MetadataItem, MetadataWithAltItem},
|
||||||
Components, LoaderTree, LoaderTreeVc, Metadata, MetadataItem, MetadataWithAltItem,
|
|
||||||
},
|
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
next_image::module::{BlurPlaceholderMode, StructuredImageModuleType},
|
next_image::module::{BlurPlaceholderMode, StructuredImageModuleType},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct LoaderTreeBuilder {
|
pub struct LoaderTreeBuilder {
|
||||||
inner_assets: IndexMap<String, AssetVc>,
|
inner_assets: IndexMap<String, Vc<Box<dyn Asset>>>,
|
||||||
counter: usize,
|
counter: usize,
|
||||||
imports: Vec<String>,
|
imports: Vec<String>,
|
||||||
loader_tree_code: String,
|
loader_tree_code: String,
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
unsupported_metadata: Vec<FileSystemPathVc>,
|
unsupported_metadata: Vec<Vc<FileSystemPath>>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
server_component_transition: ServerComponentTransition,
|
server_component_transition: ServerComponentTransition,
|
||||||
pages: Vec<FileSystemPathVc>,
|
pages: Vec<Vc<FileSystemPath>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ServerComponentTransition {
|
pub enum ServerComponentTransition {
|
||||||
Transition(TransitionVc),
|
Transition(Vc<Box<dyn Transition>>),
|
||||||
TransitionName(String),
|
TransitionName(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +67,7 @@ impl ComponentType {
|
||||||
|
|
||||||
impl LoaderTreeBuilder {
|
impl LoaderTreeBuilder {
|
||||||
fn new(
|
fn new(
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
server_component_transition: ServerComponentTransition,
|
server_component_transition: ServerComponentTransition,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -98,7 +93,7 @@ impl LoaderTreeBuilder {
|
||||||
async fn write_component(
|
async fn write_component(
|
||||||
&mut self,
|
&mut self,
|
||||||
ty: ComponentType,
|
ty: ComponentType,
|
||||||
component: Option<FileSystemPathVc>,
|
component: Option<Vc<FileSystemPath>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
use std::fmt::Write;
|
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(
|
let reference_ty = Value::new(ReferenceType::EcmaScriptModules(
|
||||||
EcmaScriptModulesReferenceSubType::Undefined,
|
EcmaScriptModulesReferenceSubType::Undefined,
|
||||||
));
|
));
|
||||||
|
@ -160,12 +155,12 @@ impl LoaderTreeBuilder {
|
||||||
}
|
}
|
||||||
ServerComponentTransition::TransitionName(transition_name) => self
|
ServerComponentTransition::TransitionName(transition_name) => self
|
||||||
.context
|
.context
|
||||||
.with_transition(transition_name.as_str())
|
.with_transition(transition_name.clone())
|
||||||
.process(source, reference_ty),
|
.process(source, reference_ty),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.inner_assets
|
self.inner_assets
|
||||||
.insert(format!("COMPONENT_{i}"), module.into());
|
.insert(format!("COMPONENT_{i}"), Vc::upcast(module));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -206,8 +201,10 @@ impl LoaderTreeBuilder {
|
||||||
.push(format!("import {identifier} from \"{inner_module_id}\";"));
|
.push(format!("import {identifier} from \"{inner_module_id}\";"));
|
||||||
self.inner_assets.insert(
|
self.inner_assets.insert(
|
||||||
inner_module_id,
|
inner_module_id,
|
||||||
StaticModuleAssetVc::new(FileSourceVc::new(path).into(), self.context.into())
|
Vc::upcast(StaticModuleAsset::new(
|
||||||
.into(),
|
Vc::upcast(FileSource::new(path)),
|
||||||
|
Vc::upcast(self.context),
|
||||||
|
)),
|
||||||
);
|
);
|
||||||
writeln!(self.loader_tree_code, " manifest: {identifier},")?;
|
writeln!(self.loader_tree_code, " manifest: {identifier},")?;
|
||||||
}
|
}
|
||||||
|
@ -249,12 +246,11 @@ impl LoaderTreeBuilder {
|
||||||
MetadataWithAltItem::Static { path, alt_path } => {
|
MetadataWithAltItem::Static { path, alt_path } => {
|
||||||
self.inner_assets.insert(
|
self.inner_assets.insert(
|
||||||
inner_module_id,
|
inner_module_id,
|
||||||
StructuredImageModuleType::create_module(
|
Vc::upcast(StructuredImageModuleType::create_module(
|
||||||
FileSourceVc::new(*path).into(),
|
Vc::upcast(FileSource::new(*path)),
|
||||||
BlurPlaceholderMode::None,
|
BlurPlaceholderMode::None,
|
||||||
self.context,
|
self.context,
|
||||||
)
|
)),
|
||||||
.into(),
|
|
||||||
);
|
);
|
||||||
writeln!(self.loader_tree_code, "{s}(async (props) => [{{")?;
|
writeln!(self.loader_tree_code, "{s}(async (props) => [{{")?;
|
||||||
writeln!(self.loader_tree_code, "{s} url: {identifier}.src,")?;
|
writeln!(self.loader_tree_code, "{s} url: {identifier}.src,")?;
|
||||||
|
@ -275,13 +271,12 @@ impl LoaderTreeBuilder {
|
||||||
.push(format!("import {identifier} from \"{inner_module_id}\";"));
|
.push(format!("import {identifier} from \"{inner_module_id}\";"));
|
||||||
self.inner_assets.insert(
|
self.inner_assets.insert(
|
||||||
inner_module_id,
|
inner_module_id,
|
||||||
self.context
|
Vc::upcast(self.context.process(
|
||||||
.process(
|
Vc::upcast(TextContentFileSource::new(Vc::upcast(FileSource::new(
|
||||||
TextContentFileSourceVc::new(FileSourceVc::new(*alt_path).into())
|
*alt_path,
|
||||||
.into(),
|
)))),
|
||||||
Value::new(ReferenceType::Internal(InnerAssetsVc::empty())),
|
Value::new(ReferenceType::Internal(InnerAssets::empty())),
|
||||||
)
|
)),
|
||||||
.into(),
|
|
||||||
);
|
);
|
||||||
writeln!(self.loader_tree_code, "{s} alt: {identifier},")?;
|
writeln!(self.loader_tree_code, "{s} alt: {identifier},")?;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +290,7 @@ impl LoaderTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion]
|
#[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;
|
use std::fmt::Write;
|
||||||
|
|
||||||
let LoaderTree {
|
let LoaderTree {
|
||||||
|
@ -344,7 +339,7 @@ impl LoaderTreeBuilder {
|
||||||
Ok(())
|
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?;
|
self.walk_tree(loader_tree).await?;
|
||||||
Ok(LoaderTreeModule {
|
Ok(LoaderTreeModule {
|
||||||
imports: self.imports,
|
imports: self.imports,
|
||||||
|
@ -359,15 +354,15 @@ impl LoaderTreeBuilder {
|
||||||
pub struct LoaderTreeModule {
|
pub struct LoaderTreeModule {
|
||||||
pub imports: Vec<String>,
|
pub imports: Vec<String>,
|
||||||
pub loader_tree_code: String,
|
pub loader_tree_code: String,
|
||||||
pub inner_assets: IndexMap<String, AssetVc>,
|
pub inner_assets: IndexMap<String, Vc<Box<dyn Asset>>>,
|
||||||
pub unsupported_metadata: Vec<FileSystemPathVc>,
|
pub unsupported_metadata: Vec<Vc<FileSystemPath>>,
|
||||||
pub pages: Vec<FileSystemPathVc>,
|
pub pages: Vec<Vc<FileSystemPath>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LoaderTreeModule {
|
impl LoaderTreeModule {
|
||||||
pub async fn build(
|
pub async fn build(
|
||||||
loader_tree: LoaderTreeVc,
|
loader_tree: Vc<LoaderTree>,
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
server_component_transition: ServerComponentTransition,
|
server_component_transition: ServerComponentTransition,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
|
|
|
@ -4,57 +4,51 @@ use mime::{APPLICATION_JAVASCRIPT_UTF_8, APPLICATION_JSON};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{
|
||||||
graph::{GraphTraversal, NonDeterministic},
|
graph::{GraphTraversal, NonDeterministic},
|
||||||
primitives::{StringReadRef, StringVc, StringsVc},
|
ReadRef, Vc,
|
||||||
};
|
};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{tasks::TryJoinIterExt, tasks_fs::File},
|
turbo::{tasks::TryJoinIterExt, tasks_fs::File},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{asset::AssetContent, introspect::Introspectable, version::VersionedContentExt},
|
||||||
asset::AssetContentVc,
|
|
||||||
introspect::{Introspectable, IntrospectableVc},
|
|
||||||
},
|
|
||||||
dev_server::source::{
|
dev_server::source::{
|
||||||
route_tree::{BaseSegment, RouteTreeVc, RouteTreesVc, RouteType},
|
route_tree::{BaseSegment, RouteTree, RouteTrees, RouteType},
|
||||||
ContentSource, ContentSourceContentVc, ContentSourceData, ContentSourceVc,
|
ContentSource, ContentSourceContent, ContentSourceData, GetContentSourceContent,
|
||||||
GetContentSourceContent, GetContentSourceContentVc,
|
|
||||||
},
|
},
|
||||||
node::render::{
|
node::render::{
|
||||||
node_api_source::NodeApiContentSourceVc, rendered_source::NodeRenderContentSourceVc,
|
node_api_source::NodeApiContentSource, rendered_source::NodeRenderContentSource,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{embed_js::next_js_file, next_config::Rewrites, util::get_asset_path_from_pathname};
|
||||||
embed_js::next_js_file,
|
|
||||||
next_config::{RewritesReadRef, RewritesVc},
|
|
||||||
util::get_asset_path_from_pathname,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A content source which creates the next.js `_devPagesManifest.json` and
|
/// A content source which creates the next.js `_devPagesManifest.json` and
|
||||||
/// `_devMiddlewareManifest.json` which are used for client side navigation.
|
/// `_devMiddlewareManifest.json` which are used for client side navigation.
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct DevManifestContentSource {
|
pub struct DevManifestContentSource {
|
||||||
pub page_roots: Vec<ContentSourceVc>,
|
pub page_roots: Vec<Vc<Box<dyn ContentSource>>>,
|
||||||
pub rewrites: RewritesVc,
|
pub rewrites: Vc<Rewrites>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl DevManifestContentSourceVc {
|
impl DevManifestContentSource {
|
||||||
/// Recursively find all routes in the `page_roots` content sources.
|
/// Recursively find all routes in the `page_roots` content sources.
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
let this = &*self.await?;
|
||||||
|
|
||||||
async fn content_source_to_pathname(
|
async fn content_source_to_pathname(
|
||||||
content_source: ContentSourceVc,
|
content_source: Vc<Box<dyn ContentSource>>,
|
||||||
) -> Result<Option<StringReadRef>> {
|
) -> Result<Option<ReadRef<String>>> {
|
||||||
// TODO This shouldn't use casts but an public api instead
|
// 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?));
|
return Ok(Some(api_source.get_pathname().await?));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(page_source) =
|
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?));
|
return Ok(Some(page_source.get_pathname().await?));
|
||||||
}
|
}
|
||||||
|
@ -63,8 +57,8 @@ impl DevManifestContentSourceVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_content_source_children(
|
async fn get_content_source_children(
|
||||||
content_source: ContentSourceVc,
|
content_source: Vc<Box<dyn ContentSource>>,
|
||||||
) -> Result<Vec<ContentSourceVc>> {
|
) -> Result<Vec<Vc<Box<dyn ContentSource>>>> {
|
||||||
Ok(content_source.get_children().await?.clone_value())
|
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.sort_by_cached_key(|s| s.split('/').map(PageSortKey::from).collect::<Vec<_>>());
|
||||||
routes.dedup();
|
routes.dedup();
|
||||||
|
|
||||||
Ok(StringsVc::cell(routes))
|
Ok(Vc::cell(routes))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively find all pages in the `page_roots` content sources
|
/// Recursively find all pages in the `page_roots` content sources
|
||||||
/// (excluding api routes).
|
/// (excluding api routes).
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
let routes = &*self.find_routes().await?;
|
||||||
|
|
||||||
// we don't need to sort as it's already sorted by `find_routes`
|
// we don't need to sort as it's already sorted by `find_routes`
|
||||||
|
@ -101,12 +95,12 @@ impl DevManifestContentSourceVc {
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(StringsVc::cell(pages))
|
Ok(Vc::cell(pages))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a build manifest with all pages.
|
/// Create a build manifest with all pages.
|
||||||
#[turbo_tasks::function]
|
#[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 this = &*self.await?;
|
||||||
|
|
||||||
let sorted_pages = &*self.find_pages().await?;
|
let sorted_pages = &*self.find_pages().await?;
|
||||||
|
@ -129,7 +123,7 @@ impl DevManifestContentSourceVc {
|
||||||
routes,
|
routes,
|
||||||
};
|
};
|
||||||
|
|
||||||
let manifest = next_js_file("entry/manifest/buildManifest.js")
|
let manifest = next_js_file("entry/manifest/buildManifest.js".to_string())
|
||||||
.await?
|
.await?
|
||||||
.as_content()
|
.as_content()
|
||||||
.context("embedded buildManifest file missing")?
|
.context("embedded buildManifest file missing")?
|
||||||
|
@ -137,7 +131,7 @@ impl DevManifestContentSourceVc {
|
||||||
.to_str()?
|
.to_str()?
|
||||||
.replace("$$MANIFEST$$", &serde_json::to_string(&manifest)?);
|
.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")]
|
#[serde(rename_all = "camelCase")]
|
||||||
struct BuildManifest<'a> {
|
struct BuildManifest<'a> {
|
||||||
#[serde(rename = "__rewrites")]
|
#[serde(rename = "__rewrites")]
|
||||||
rewrites: RewritesReadRef,
|
rewrites: ReadRef<Rewrites>,
|
||||||
sorted_pages: &'a Vec<String>,
|
sorted_pages: &'a Vec<String>,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -160,22 +154,22 @@ const DEV_MIDDLEWARE_MANIFEST_PATHNAME: &str =
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ContentSource for DevManifestContentSource {
|
impl ContentSource for DevManifestContentSource {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn get_routes(self_vc: DevManifestContentSourceVc) -> RouteTreeVc {
|
fn get_routes(self: Vc<Self>) -> Vc<RouteTree> {
|
||||||
RouteTreesVc::cell(vec![
|
Vc::<RouteTrees>::cell(vec![
|
||||||
RouteTreeVc::new_route(
|
RouteTree::new_route(
|
||||||
BaseSegment::from_static_pathname(DEV_MANIFEST_PATHNAME).collect(),
|
BaseSegment::from_static_pathname(DEV_MANIFEST_PATHNAME).collect(),
|
||||||
RouteType::Exact,
|
RouteType::Exact,
|
||||||
self_vc.into(),
|
Vc::upcast(self),
|
||||||
),
|
),
|
||||||
RouteTreeVc::new_route(
|
RouteTree::new_route(
|
||||||
BaseSegment::from_static_pathname(BUILD_MANIFEST_PATHNAME).collect(),
|
BaseSegment::from_static_pathname(BUILD_MANIFEST_PATHNAME).collect(),
|
||||||
RouteType::Exact,
|
RouteType::Exact,
|
||||||
self_vc.into(),
|
Vc::upcast(self),
|
||||||
),
|
),
|
||||||
RouteTreeVc::new_route(
|
RouteTree::new_route(
|
||||||
BaseSegment::from_static_pathname(DEV_MIDDLEWARE_MANIFEST_PATHNAME).collect(),
|
BaseSegment::from_static_pathname(DEV_MIDDLEWARE_MANIFEST_PATHNAME).collect(),
|
||||||
RouteType::Exact,
|
RouteType::Exact,
|
||||||
self_vc.into(),
|
Vc::upcast(self),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
.merge()
|
.merge()
|
||||||
|
@ -186,13 +180,13 @@ impl ContentSource for DevManifestContentSource {
|
||||||
impl GetContentSourceContent for DevManifestContentSource {
|
impl GetContentSourceContent for DevManifestContentSource {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn get(
|
async fn get(
|
||||||
self_vc: DevManifestContentSourceVc,
|
self: Vc<Self>,
|
||||||
path: &str,
|
path: String,
|
||||||
_data: turbo_tasks::Value<ContentSourceData>,
|
_data: turbo_tasks::Value<ContentSourceData>,
|
||||||
) -> Result<ContentSourceContentVc> {
|
) -> Result<Vc<ContentSourceContent>> {
|
||||||
let manifest_file = match path {
|
let manifest_file = match path.as_str() {
|
||||||
DEV_MANIFEST_PATHNAME => {
|
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!({
|
File::from(serde_json::to_string(&serde_json::json!({
|
||||||
"pages": pages,
|
"pages": pages,
|
||||||
|
@ -200,7 +194,7 @@ impl GetContentSourceContent for DevManifestContentSource {
|
||||||
.with_content_type(APPLICATION_JSON)
|
.with_content_type(APPLICATION_JSON)
|
||||||
}
|
}
|
||||||
BUILD_MANIFEST_PATHNAME => {
|
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)
|
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),
|
_ => bail!("unknown path: {}", path),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ContentSourceContentVc::static_content(
|
Ok(ContentSourceContent::static_content(
|
||||||
AssetContentVc::from(manifest_file).into(),
|
AssetContent::file(manifest_file.into()).versioned(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,13 +218,13 @@ impl GetContentSourceContent for DevManifestContentSource {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Introspectable for DevManifestContentSource {
|
impl Introspectable for DevManifestContentSource {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ty(&self) -> StringVc {
|
fn ty(&self) -> Vc<String> {
|
||||||
StringVc::cell("dev manifest source".to_string())
|
Vc::cell("dev manifest source".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn details(&self) -> StringVc {
|
fn details(&self) -> Vc<String> {
|
||||||
StringVc::cell(
|
Vc::cell(
|
||||||
"provides _devPagesManifest.json, _buildManifest.js and _devMiddlewareManifest.json."
|
"provides _devPagesManifest.json, _buildManifest.js and _devMiddlewareManifest.json."
|
||||||
.to_string(),
|
.to_string(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,43 +1,43 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use turbo_tasks::{primitives::StringVc, TryJoinIterExt, ValueToString};
|
use turbo_tasks::{TryJoinIterExt, ValueToString, Vc};
|
||||||
use turbo_tasks_fs::FileSystemPathVc;
|
use turbo_tasks_fs::FileSystemPath;
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc},
|
core::issue::{Issue, IssueSeverity},
|
||||||
ecmascript::utils::FormatIter,
|
ecmascript::utils::FormatIter,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct UnsupportedDynamicMetadataIssue {
|
pub struct UnsupportedDynamicMetadataIssue {
|
||||||
pub app_dir: FileSystemPathVc,
|
pub app_dir: Vc<FileSystemPath>,
|
||||||
pub files: Vec<FileSystemPathVc>,
|
pub files: Vec<Vc<FileSystemPath>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Issue for UnsupportedDynamicMetadataIssue {
|
impl Issue for UnsupportedDynamicMetadataIssue {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn severity(&self) -> IssueSeverityVc {
|
fn severity(&self) -> Vc<IssueSeverity> {
|
||||||
IssueSeverity::Warning.into()
|
IssueSeverity::Warning.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn category(&self) -> StringVc {
|
fn category(&self) -> Vc<String> {
|
||||||
StringVc::cell("unsupported".to_string())
|
Vc::cell("unsupported".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn context(&self) -> FileSystemPathVc {
|
fn context(&self) -> Vc<FileSystemPath> {
|
||||||
self.app_dir
|
self.app_dir
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn title(&self) -> StringVc {
|
fn title(&self) -> Vc<String> {
|
||||||
StringVc::cell(
|
Vc::cell(
|
||||||
"Dynamic metadata from filesystem is currently not supported in Turbopack".to_string(),
|
"Dynamic metadata from filesystem is currently not supported in Turbopack".to_string(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn description(&self) -> Result<StringVc> {
|
async fn description(&self) -> Result<Vc<String>> {
|
||||||
let mut files = self
|
let mut files = self
|
||||||
.files
|
.files
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -45,7 +45,7 @@ impl Issue for UnsupportedDynamicMetadataIssue {
|
||||||
.try_join()
|
.try_join()
|
||||||
.await?;
|
.await?;
|
||||||
files.sort();
|
files.sort();
|
||||||
Ok(StringVc::cell(format!(
|
Ok(Vc::cell(format!(
|
||||||
"The following files were found in the app directory, but are not supported by \
|
"The following files were found in the app directory, but are not supported by \
|
||||||
Turbopack. They are ignored:\n{}",
|
Turbopack. They are ignored:\n{}",
|
||||||
FormatIter(|| files.iter().flat_map(|file| vec!["\n- ", file]))
|
FormatIter(|| files.iter().flat_map(|file| vec!["\n- ", file]))
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use turbo_tasks::primitives::StringVc;
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::FileSystemPathVc,
|
turbo::tasks_fs::FileSystemPath, turbopack::core::resolve::options::ImportMapping,
|
||||||
turbopack::core::resolve::options::{ImportMapping, ImportMappingVc},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::next_import_map::get_next_package;
|
use crate::next_import_map::get_next_package;
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_postcss_package_mapping(
|
pub async fn get_postcss_package_mapping(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
) -> Result<ImportMappingVc> {
|
) -> Result<Vc<ImportMapping>> {
|
||||||
Ok(ImportMapping::Alternatives(vec![
|
Ok(ImportMapping::Alternatives(vec![
|
||||||
// Prefer the local installed version over the next.js version
|
// Prefer the local installed version over the next.js version
|
||||||
ImportMapping::PrimaryAlternative("postcss".to_string(), Some(project_path)).cell(),
|
ImportMapping::PrimaryAlternative("postcss".to_string(), Some(project_path)).cell(),
|
||||||
|
@ -25,8 +24,8 @@ pub async fn get_postcss_package_mapping(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_external_next_compiled_package_mapping(
|
pub async fn get_external_next_compiled_package_mapping(
|
||||||
package_name: StringVc,
|
package_name: Vc<String>,
|
||||||
) -> Result<ImportMappingVc> {
|
) -> Result<Vc<ImportMapping>> {
|
||||||
Ok(
|
Ok(
|
||||||
ImportMapping::Alternatives(vec![ImportMapping::External(Some(format!(
|
ImportMapping::Alternatives(vec![ImportMapping::External(Some(format!(
|
||||||
"next/dist/compiled/{}",
|
"next/dist/compiled/{}",
|
||||||
|
|
|
@ -1,38 +1,33 @@
|
||||||
use core::{default::Default, result::Result::Ok};
|
use core::{default::Default, result::Result::Ok};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{Value, Vc};
|
||||||
primitives::{OptionStringVc, StringVc},
|
|
||||||
Value,
|
|
||||||
};
|
|
||||||
use turbo_tasks_fs::FileSystem;
|
use turbo_tasks_fs::FileSystem;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{tasks_env::ProcessEnvVc, tasks_fs::FileSystemPathVc},
|
turbo::{tasks_env::ProcessEnv, tasks_fs::FileSystemPath},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
compile_time_defines,
|
compile_time_defines,
|
||||||
compile_time_info::{
|
compile_time_info::{
|
||||||
CompileTimeDefines, CompileTimeDefinesVc, CompileTimeInfo, CompileTimeInfoVc,
|
CompileTimeDefines, CompileTimeInfo, FreeVarReference, FreeVarReferences,
|
||||||
FreeVarReference, FreeVarReferencesVc,
|
|
||||||
},
|
},
|
||||||
environment::{BrowserEnvironment, EnvironmentVc, ExecutionEnvironment},
|
environment::{BrowserEnvironment, Environment, ExecutionEnvironment},
|
||||||
free_var_references,
|
free_var_references,
|
||||||
resolve::{parse::RequestVc, pattern::Pattern},
|
resolve::{parse::Request, pattern::Pattern},
|
||||||
},
|
},
|
||||||
dev::{react_refresh::assert_can_resolve_react_refresh, DevChunkingContextVc},
|
dev::{react_refresh::assert_can_resolve_react_refresh, DevChunkingContext},
|
||||||
ecmascript::{chunk::EcmascriptChunkingContextVc, TransformPluginVc},
|
ecmascript::chunk::EcmascriptChunkingContext,
|
||||||
ecmascript_plugin::transform::directives::server::ServerDirectiveTransformer,
|
ecmascript_plugin::transform::directives::server::ServerDirectiveTransformer,
|
||||||
env::ProcessEnvAssetVc,
|
env::ProcessEnvAsset,
|
||||||
node::execution_context::ExecutionContextVc,
|
node::execution_context::ExecutionContext,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
condition::ContextCondition,
|
condition::ContextCondition,
|
||||||
module_options::{
|
module_options::{
|
||||||
module_options_context::{ModuleOptionsContext, ModuleOptionsContextVc},
|
module_options_context::ModuleOptionsContext, CustomEcmascriptTransformPlugins,
|
||||||
CustomEcmascriptTransformPlugins, CustomEcmascriptTransformPluginsVc,
|
|
||||||
JsxTransformOptions, MdxTransformModuleOptions, PostCssTransformOptions,
|
JsxTransformOptions, MdxTransformModuleOptions, PostCssTransformOptions,
|
||||||
TypescriptTransformOptions, WebpackLoadersOptions,
|
TypescriptTransformOptions, WebpackLoadersOptions,
|
||||||
},
|
},
|
||||||
resolve_options_context::{ResolveOptionsContext, ResolveOptionsContextVc},
|
resolve_options_context::ResolveOptionsContext,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -44,14 +39,14 @@ use crate::{
|
||||||
env::env_for_js,
|
env::env_for_js,
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
next_build::{get_external_next_compiled_package_mapping, get_postcss_package_mapping},
|
next_build::{get_external_next_compiled_package_mapping, get_postcss_package_mapping},
|
||||||
next_client::runtime_entry::{RuntimeEntriesVc, RuntimeEntry},
|
next_client::runtime_entry::{RuntimeEntries, RuntimeEntry},
|
||||||
next_config::NextConfigVc,
|
next_config::NextConfig,
|
||||||
next_import_map::{
|
next_import_map::{
|
||||||
get_next_client_fallback_import_map, get_next_client_import_map,
|
get_next_client_fallback_import_map, get_next_client_import_map,
|
||||||
get_next_client_resolved_map, mdx_import_source_file,
|
get_next_client_resolved_map, mdx_import_source_file,
|
||||||
},
|
},
|
||||||
next_shared::{
|
next_shared::{
|
||||||
resolve::UnsupportedModulesResolvePluginVc,
|
resolve::UnsupportedModulesResolvePlugin,
|
||||||
transforms::{
|
transforms::{
|
||||||
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
|
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
|
||||||
styled_components::get_styled_components_transform_plugin,
|
styled_components::get_styled_components_transform_plugin,
|
||||||
|
@ -80,12 +75,12 @@ fn defines(mode: NextMode) -> CompileTimeDefines {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn next_client_defines(mode: NextMode) -> CompileTimeDefinesVc {
|
fn next_client_defines(mode: NextMode) -> Vc<CompileTimeDefines> {
|
||||||
defines(mode).cell()
|
defines(mode).cell()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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!(
|
Ok(free_var_references!(
|
||||||
..defines(mode).into_iter(),
|
..defines(mode).into_iter(),
|
||||||
Buffer = FreeVarReference::EcmaScriptModule {
|
Buffer = FreeVarReference::EcmaScriptModule {
|
||||||
|
@ -103,18 +98,19 @@ async fn next_client_free_vars(mode: NextMode) -> Result<FreeVarReferencesVc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn get_client_compile_time_info(mode: NextMode, browserslist_query: &str) -> CompileTimeInfoVc {
|
pub fn get_client_compile_time_info(
|
||||||
CompileTimeInfo::builder(EnvironmentVc::new(Value::new(
|
mode: NextMode,
|
||||||
ExecutionEnvironment::Browser(
|
browserslist_query: String,
|
||||||
BrowserEnvironment {
|
) -> Vc<CompileTimeInfo> {
|
||||||
dom: true,
|
CompileTimeInfo::builder(Environment::new(Value::new(ExecutionEnvironment::Browser(
|
||||||
web_worker: false,
|
BrowserEnvironment {
|
||||||
service_worker: false,
|
dom: true,
|
||||||
browserslist_query: browserslist_query.to_owned(),
|
web_worker: false,
|
||||||
}
|
service_worker: false,
|
||||||
.into(),
|
browserslist_query: browserslist_query.to_owned(),
|
||||||
),
|
}
|
||||||
)))
|
.into(),
|
||||||
|
))))
|
||||||
.defines(next_client_defines(mode))
|
.defines(next_client_defines(mode))
|
||||||
.free_var_references(next_client_free_vars(mode))
|
.free_var_references(next_client_free_vars(mode))
|
||||||
.cell()
|
.cell()
|
||||||
|
@ -123,20 +119,20 @@ pub fn get_client_compile_time_info(mode: NextMode, browserslist_query: &str) ->
|
||||||
#[turbo_tasks::value(serialization = "auto_for_input")]
|
#[turbo_tasks::value(serialization = "auto_for_input")]
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord)]
|
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord)]
|
||||||
pub enum ClientContextType {
|
pub enum ClientContextType {
|
||||||
Pages { pages_dir: FileSystemPathVc },
|
Pages { pages_dir: Vc<FileSystemPath> },
|
||||||
App { app_dir: FileSystemPathVc },
|
App { app_dir: Vc<FileSystemPath> },
|
||||||
Fallback,
|
Fallback,
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_client_resolve_options_context(
|
pub async fn get_client_resolve_options_context(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
ty: Value<ClientContextType>,
|
ty: Value<ClientContextType>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
) -> Result<ResolveOptionsContextVc> {
|
) -> Result<Vc<ResolveOptionsContext>> {
|
||||||
let next_client_import_map =
|
let next_client_import_map =
|
||||||
get_next_client_import_map(project_path, ty, next_config, execution_context);
|
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);
|
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),
|
resolved_map: Some(next_client_resolved_map),
|
||||||
browser: true,
|
browser: true,
|
||||||
module: true,
|
module: true,
|
||||||
plugins: vec![UnsupportedModulesResolvePluginVc::new(project_path).into()],
|
plugins: vec![Vc::upcast(UnsupportedModulesResolvePlugin::new(
|
||||||
|
project_path,
|
||||||
|
))],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
Ok(ResolveOptionsContext {
|
Ok(ResolveOptionsContext {
|
||||||
|
@ -166,13 +164,13 @@ pub async fn get_client_resolve_options_context(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_client_module_options_context(
|
pub async fn get_client_module_options_context(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
env: EnvironmentVc,
|
env: Vc<Environment>,
|
||||||
ty: Value<ClientContextType>,
|
ty: Value<ClientContextType>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
) -> Result<ModuleOptionsContextVc> {
|
) -> Result<Vc<ModuleOptionsContext>> {
|
||||||
let custom_rules = get_next_client_transforms_rules(next_config, ty.into_value(), mode).await?;
|
let custom_rules = get_next_client_transforms_rules(next_config, ty.into_value(), mode).await?;
|
||||||
let resolve_options_context =
|
let resolve_options_context =
|
||||||
get_client_resolve_options_context(project_path, ty, mode, next_config, execution_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| {
|
let enable_webpack_loaders = webpack_rules.map(|rules| {
|
||||||
WebpackLoadersOptions {
|
WebpackLoadersOptions {
|
||||||
rules,
|
rules,
|
||||||
loader_runner_package: Some(get_external_next_compiled_package_mapping(
|
loader_runner_package: Some(get_external_next_compiled_package_mapping(Vc::cell(
|
||||||
StringVc::cell("loader-runner".to_owned()),
|
"loader-runner".to_owned(),
|
||||||
)),
|
))),
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
});
|
});
|
||||||
|
@ -210,19 +208,17 @@ pub async fn get_client_module_options_context(
|
||||||
*get_emotion_transform_plugin(next_config).await?,
|
*get_emotion_transform_plugin(next_config).await?,
|
||||||
*get_styled_components_transform_plugin(next_config).await?,
|
*get_styled_components_transform_plugin(next_config).await?,
|
||||||
*get_styled_jsx_transform_plugin().await?,
|
*get_styled_jsx_transform_plugin().await?,
|
||||||
Some(TransformPluginVc::cell(Box::new(
|
Some(Vc::cell(Box::new(ServerDirectiveTransformer::new(
|
||||||
ServerDirectiveTransformer::new(
|
// ServerDirective is not implemented yet and always reports an issue.
|
||||||
// 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.
|
||||||
// We don't have to pass a valid transition name yet, but the API is prepared.
|
&Vc::cell("TODO".to_string()),
|
||||||
&StringVc::cell("TODO".to_string()),
|
)) as _)),
|
||||||
),
|
|
||||||
))),
|
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||||
CustomEcmascriptTransformPlugins {
|
CustomEcmascriptTransformPlugins {
|
||||||
source_transforms,
|
source_transforms,
|
||||||
output_transforms: vec![],
|
output_transforms: vec![],
|
||||||
|
@ -280,43 +276,41 @@ pub async fn get_client_module_options_context(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn get_client_chunking_context(
|
pub fn get_client_chunking_context(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
client_root: FileSystemPathVc,
|
client_root: Vc<FileSystemPath>,
|
||||||
environment: EnvironmentVc,
|
environment: Vc<Environment>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
) -> EcmascriptChunkingContextVc {
|
) -> Vc<Box<dyn EcmascriptChunkingContext>> {
|
||||||
let builder = DevChunkingContextVc::builder(
|
let builder = DevChunkingContext::builder(
|
||||||
project_path,
|
project_path,
|
||||||
client_root,
|
client_root,
|
||||||
client_root.join("_next/static/chunks"),
|
client_root.join("_next/static/chunks".to_string()),
|
||||||
get_client_assets_path(client_root),
|
get_client_assets_path(client_root),
|
||||||
environment,
|
environment,
|
||||||
);
|
);
|
||||||
|
|
||||||
let builder = match mode {
|
let builder = match mode {
|
||||||
NextMode::Development => builder.hot_module_replacement(),
|
NextMode::Development => builder.hot_module_replacement(),
|
||||||
NextMode::Build => {
|
NextMode::Build => builder.chunk_base_path(Vc::cell(Some("_next/".to_string()))),
|
||||||
builder.chunk_base_path(OptionStringVc::cell(Some("_next/".to_string())))
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
builder.build().into()
|
Vc::upcast(builder.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn get_client_assets_path(client_root: FileSystemPathVc) -> FileSystemPathVc {
|
pub fn get_client_assets_path(client_root: Vc<FileSystemPath>) -> Vc<FileSystemPath> {
|
||||||
client_root.join("_next/static/media")
|
client_root.join("_next/static/media".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_client_runtime_entries(
|
pub async fn get_client_runtime_entries(
|
||||||
project_root: FileSystemPathVc,
|
project_root: Vc<FileSystemPath>,
|
||||||
env: ProcessEnvVc,
|
env: Vc<Box<dyn ProcessEnv>>,
|
||||||
ty: Value<ClientContextType>,
|
ty: Value<ClientContextType>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
) -> Result<RuntimeEntriesVc> {
|
) -> Result<Vc<RuntimeEntries>> {
|
||||||
let mut runtime_entries = vec![];
|
let mut runtime_entries = vec![];
|
||||||
|
|
||||||
if matches!(
|
if matches!(
|
||||||
|
@ -324,9 +318,10 @@ pub async fn get_client_runtime_entries(
|
||||||
ClientContextType::App { .. } | ClientContextType::Pages { .. },
|
ClientContextType::App { .. } | ClientContextType::Pages { .. },
|
||||||
) {
|
) {
|
||||||
runtime_entries.push(
|
runtime_entries.push(
|
||||||
RuntimeEntry::Source(
|
RuntimeEntry::Source(Vc::upcast(ProcessEnvAsset::new(
|
||||||
ProcessEnvAssetVc::new(project_root, env_for_js(env, true, next_config)).into(),
|
project_root,
|
||||||
)
|
env_for_js(env, true, next_config),
|
||||||
|
)))
|
||||||
.cell(),
|
.cell(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -349,17 +344,18 @@ pub async fn get_client_runtime_entries(
|
||||||
// because the bootstrap contains JSX which requires Refresh's global
|
// because the bootstrap contains JSX which requires Refresh's global
|
||||||
// functions to be available.
|
// functions to be available.
|
||||||
if let Some(request) = enable_react_refresh {
|
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 {
|
NextMode::Build => match *ty {
|
||||||
ClientContextType::App { .. } => {
|
ClientContextType::App { .. } => {
|
||||||
runtime_entries.push(
|
runtime_entries.push(
|
||||||
RuntimeEntry::Request(
|
RuntimeEntry::Request(
|
||||||
RequestVc::parse(Value::new(Pattern::Constant(
|
Request::parse(Value::new(Pattern::Constant(
|
||||||
"./build/client/app-bootstrap.ts".to_string(),
|
"./build/client/app-bootstrap.ts".to_string(),
|
||||||
))),
|
))),
|
||||||
next_js_fs().root().join("_"),
|
next_js_fs().root().join("_".to_string()),
|
||||||
)
|
)
|
||||||
.cell(),
|
.cell(),
|
||||||
);
|
);
|
||||||
|
@ -367,10 +363,10 @@ pub async fn get_client_runtime_entries(
|
||||||
ClientContextType::Pages { .. } => {
|
ClientContextType::Pages { .. } => {
|
||||||
runtime_entries.push(
|
runtime_entries.push(
|
||||||
RuntimeEntry::Request(
|
RuntimeEntry::Request(
|
||||||
RequestVc::parse(Value::new(Pattern::Constant(
|
Request::parse(Value::new(Pattern::Constant(
|
||||||
"./build/client/bootstrap.ts".to_string(),
|
"./build/client/bootstrap.ts".to_string(),
|
||||||
))),
|
))),
|
||||||
next_js_fs().root().join("_"),
|
next_js_fs().root().join("_".to_string()),
|
||||||
)
|
)
|
||||||
.cell(),
|
.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_chunking_context, get_client_compile_time_info, get_client_module_options_context,
|
||||||
get_client_resolve_options_context, get_client_runtime_entries, ClientContextType,
|
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;
|
pub use transition::NextClientTransition;
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{tasks::ValueToString, tasks_fs::FileSystemPathVc},
|
turbo::{tasks::ValueToString, tasks_fs::FileSystemPath},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::Asset,
|
asset::Asset,
|
||||||
chunk::{EvaluatableAssetVc, EvaluatableAssetsVc},
|
chunk::{EvaluatableAsset, EvaluatableAssetExt, EvaluatableAssets},
|
||||||
context::AssetContextVc,
|
context::AssetContext,
|
||||||
issue::{IssueSeverity, OptionIssueSourceVc},
|
issue::{IssueSeverity, OptionIssueSource},
|
||||||
resolve::{origin::PlainResolveOriginVc, parse::RequestVc},
|
resolve::{origin::PlainResolveOrigin, parse::Request},
|
||||||
source::SourceVc,
|
source::Source,
|
||||||
},
|
},
|
||||||
ecmascript::resolve::cjs_resolve,
|
ecmascript::resolve::cjs_resolve,
|
||||||
},
|
},
|
||||||
|
@ -16,29 +17,30 @@ use turbopack_binding::{
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub enum RuntimeEntry {
|
pub enum RuntimeEntry {
|
||||||
Request(RequestVc, FileSystemPathVc),
|
Request(Vc<Request>, Vc<FileSystemPath>),
|
||||||
Evaluatable(EvaluatableAssetVc),
|
Evaluatable(Vc<Box<dyn EvaluatableAsset>>),
|
||||||
Source(SourceVc),
|
Source(Vc<Box<dyn Source>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl RuntimeEntryVc {
|
impl RuntimeEntry {
|
||||||
#[turbo_tasks::function]
|
#[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? {
|
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) => {
|
RuntimeEntry::Source(source) => {
|
||||||
return Ok(EvaluatableAssetsVc::one(EvaluatableAssetVc::from_source(
|
return Ok(EvaluatableAssets::one(source.to_evaluatable(context)));
|
||||||
source, context,
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
RuntimeEntry::Request(r, path) => (r, path),
|
RuntimeEntry::Request(r, path) => (r, path),
|
||||||
};
|
};
|
||||||
|
|
||||||
let assets = cjs_resolve(
|
let assets = cjs_resolve(
|
||||||
PlainResolveOriginVc::new(context, path).into(),
|
Vc::upcast(PlainResolveOrigin::new(context, path)),
|
||||||
request,
|
request,
|
||||||
OptionIssueSourceVc::none(),
|
OptionIssueSource::none(),
|
||||||
IssueSeverity::Error.cell(),
|
IssueSeverity::Error.cell(),
|
||||||
)
|
)
|
||||||
.primary_assets()
|
.primary_assets()
|
||||||
|
@ -46,7 +48,9 @@ impl RuntimeEntryVc {
|
||||||
|
|
||||||
let mut runtime_entries = Vec::with_capacity(assets.len());
|
let mut runtime_entries = Vec::with_capacity(assets.len());
|
||||||
for asset in &assets {
|
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);
|
runtime_entries.push(entry);
|
||||||
} else {
|
} else {
|
||||||
bail!(
|
bail!(
|
||||||
|
@ -56,17 +60,20 @@ impl RuntimeEntryVc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(EvaluatableAssetsVc::cell(runtime_entries))
|
Ok(Vc::cell(runtime_entries))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(transparent)]
|
#[turbo_tasks::value(transparent)]
|
||||||
pub struct RuntimeEntries(Vec<RuntimeEntryVc>);
|
pub struct RuntimeEntries(Vec<Vc<RuntimeEntry>>);
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl RuntimeEntriesVc {
|
impl RuntimeEntries {
|
||||||
#[turbo_tasks::function]
|
#[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();
|
let mut runtime_entries = Vec::new();
|
||||||
|
|
||||||
for reference in &self.await? {
|
for reference in &self.await? {
|
||||||
|
@ -74,6 +81,6 @@ impl RuntimeEntriesVc {
|
||||||
runtime_entries.extend(&resolved_entries);
|
runtime_entries.extend(&resolved_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(EvaluatableAssetsVc::cell(runtime_entries))
|
Ok(Vc::cell(runtime_entries))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use next_transform_strip_page_exports::ExportFilter;
|
use next_transform_strip_page_exports::ExportFilter;
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::turbopack::turbopack::module_options::ModuleRule;
|
use turbopack_binding::turbopack::turbopack::module_options::ModuleRule;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
next_client::context::ClientContextType,
|
next_client::context::ClientContextType,
|
||||||
next_config::NextConfigVc,
|
next_config::NextConfig,
|
||||||
next_shared::transforms::{
|
next_shared::transforms::{
|
||||||
get_next_dynamic_transform_rule, get_next_font_transform_rule, get_next_image_rule,
|
get_next_dynamic_transform_rule, get_next_font_transform_rule, get_next_image_rule,
|
||||||
get_next_modularize_imports_rule, get_next_pages_transforms_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
|
/// Returns a list of module rules which apply client-side, Next.js-specific
|
||||||
/// transforms.
|
/// transforms.
|
||||||
pub async fn get_next_client_transforms_rules(
|
pub async fn get_next_client_transforms_rules(
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
context_ty: ClientContextType,
|
context_ty: ClientContextType,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
) -> Result<Vec<ModuleRule>> {
|
) -> Result<Vec<ModuleRule>> {
|
||||||
|
|
|
@ -1,25 +1,20 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use indexmap::indexmap;
|
use indexmap::indexmap;
|
||||||
use turbo_tasks::Value;
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
chunk::{ChunkingContext, ChunkingContextVc},
|
chunk::ChunkingContext, compile_time_info::CompileTimeInfo, context::AssetContext,
|
||||||
compile_time_info::CompileTimeInfoVc,
|
module::Module, reference_type::ReferenceType,
|
||||||
context::AssetContext,
|
|
||||||
module::ModuleVc,
|
|
||||||
reference_type::{InnerAssetsVc, ReferenceType},
|
|
||||||
},
|
},
|
||||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
ecmascript::chunk::EcmascriptChunkPlaceable,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
ecmascript::chunk_group_files_asset::ChunkGroupFilesAsset,
|
ecmascript::chunk_group_files_asset::ChunkGroupFilesAsset,
|
||||||
module_options::ModuleOptionsContextVc,
|
module_options::ModuleOptionsContext, resolve_options_context::ResolveOptionsContext,
|
||||||
resolve_options_context::ResolveOptionsContextVc,
|
transition::Transition, ModuleAssetContext,
|
||||||
transition::{Transition, TransitionVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::runtime_entry::RuntimeEntriesVc;
|
use super::runtime_entry::RuntimeEntries;
|
||||||
use crate::embed_js::next_asset;
|
use crate::embed_js::next_asset;
|
||||||
|
|
||||||
/// Makes a transition into a next.js client context.
|
/// Makes a transition into a next.js client context.
|
||||||
|
@ -30,11 +25,11 @@ use crate::embed_js::next_asset;
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextClientTransition {
|
pub struct NextClientTransition {
|
||||||
pub is_app: bool,
|
pub is_app: bool,
|
||||||
pub client_compile_time_info: CompileTimeInfoVc,
|
pub client_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
pub client_module_options_context: ModuleOptionsContextVc,
|
pub client_module_options_context: Vc<ModuleOptionsContext>,
|
||||||
pub client_resolve_options_context: ResolveOptionsContextVc,
|
pub client_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||||
pub client_chunking_context: ChunkingContextVc,
|
pub client_chunking_context: Vc<Box<dyn ChunkingContext>>,
|
||||||
pub runtime_entries: RuntimeEntriesVc,
|
pub runtime_entries: Vc<RuntimeEntries>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
|
@ -42,60 +37,65 @@ impl Transition for NextClientTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_compile_time_info(
|
fn process_compile_time_info(
|
||||||
&self,
|
&self,
|
||||||
_compile_time_info: CompileTimeInfoVc,
|
_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
) -> CompileTimeInfoVc {
|
) -> Vc<CompileTimeInfo> {
|
||||||
self.client_compile_time_info
|
self.client_compile_time_info
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_module_options_context(
|
fn process_module_options_context(
|
||||||
&self,
|
&self,
|
||||||
_context: ModuleOptionsContextVc,
|
_context: Vc<ModuleOptionsContext>,
|
||||||
) -> ModuleOptionsContextVc {
|
) -> Vc<ModuleOptionsContext> {
|
||||||
self.client_module_options_context
|
self.client_module_options_context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_resolve_options_context(
|
fn process_resolve_options_context(
|
||||||
&self,
|
&self,
|
||||||
_context: ResolveOptionsContextVc,
|
_context: Vc<ResolveOptionsContext>,
|
||||||
) -> ResolveOptionsContextVc {
|
) -> Vc<ResolveOptionsContext> {
|
||||||
self.client_resolve_options_context
|
self.client_resolve_options_context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn process_module(
|
async fn process_module(
|
||||||
&self,
|
&self,
|
||||||
asset: ModuleVc,
|
asset: Vc<Box<dyn Module>>,
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
) -> Result<ModuleVc> {
|
) -> Result<Vc<Box<dyn Module>>> {
|
||||||
let asset = if !self.is_app {
|
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(
|
context.process(
|
||||||
internal_asset,
|
internal_asset,
|
||||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap! {
|
Value::new(ReferenceType::Internal(Vc::cell(indexmap! {
|
||||||
"PAGE".to_string() => asset.into()
|
"PAGE".to_string() => Vc::upcast(asset)
|
||||||
}))),
|
}))),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
asset
|
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");
|
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 {
|
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
|
// 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.
|
// 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,
|
chunking_context: self.client_chunking_context,
|
||||||
runtime_entries: Some(runtime_entries),
|
runtime_entries: Some(runtime_entries),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(asset.cell().into())
|
Ok(Vc::upcast(asset.cell()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +1,48 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use turbo_tasks::Value;
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::FileSystemPathVc,
|
turbo::tasks_fs::FileSystemPath,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{compile_time_info::CompileTimeInfoVc, module::ModuleVc},
|
core::{compile_time_info::CompileTimeInfo, module::Module},
|
||||||
ecmascript::chunk::EcmascriptChunkingContextVc,
|
ecmascript::chunk::EcmascriptChunkingContext,
|
||||||
node::execution_context::ExecutionContextVc,
|
node::execution_context::ExecutionContext,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
ecmascript::chunk::EcmascriptChunkPlaceable, module_options::ModuleOptionsContext,
|
||||||
module_options::ModuleOptionsContextVc,
|
resolve_options_context::ResolveOptionsContext, transition::Transition,
|
||||||
resolve_options_context::ResolveOptionsContextVc,
|
ModuleAssetContext,
|
||||||
transition::{Transition, TransitionVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::with_chunks::WithChunksAssetVc;
|
use super::with_chunks::WithChunksAsset;
|
||||||
use crate::{
|
use crate::{
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
next_client::context::{
|
next_client::context::{
|
||||||
get_client_module_options_context, get_client_resolve_options_context, ClientContextType,
|
get_client_module_options_context, get_client_resolve_options_context, ClientContextType,
|
||||||
},
|
},
|
||||||
next_config::NextConfigVc,
|
next_config::NextConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextClientChunksTransition {
|
pub struct NextClientChunksTransition {
|
||||||
pub client_compile_time_info: CompileTimeInfoVc,
|
pub client_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
pub client_module_options_context: ModuleOptionsContextVc,
|
pub client_module_options_context: Vc<ModuleOptionsContext>,
|
||||||
pub client_resolve_options_context: ResolveOptionsContextVc,
|
pub client_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||||
pub client_chunking_context: EcmascriptChunkingContextVc,
|
pub client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextClientChunksTransitionVc {
|
impl NextClientChunksTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
ty: Value<ClientContextType>,
|
ty: Value<ClientContextType>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
client_chunking_context: EcmascriptChunkingContextVc,
|
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
client_compile_time_info: CompileTimeInfoVc,
|
client_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
) -> NextClientChunksTransitionVc {
|
) -> Vc<NextClientChunksTransition> {
|
||||||
let client_module_options_context = get_client_module_options_context(
|
let client_module_options_context = get_client_module_options_context(
|
||||||
project_path,
|
project_path,
|
||||||
execution_context,
|
execution_context,
|
||||||
|
@ -74,36 +72,41 @@ impl Transition for NextClientChunksTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_compile_time_info(
|
fn process_compile_time_info(
|
||||||
&self,
|
&self,
|
||||||
_compile_time_info: CompileTimeInfoVc,
|
_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
) -> CompileTimeInfoVc {
|
) -> Vc<CompileTimeInfo> {
|
||||||
self.client_compile_time_info
|
self.client_compile_time_info
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_module_options_context(
|
fn process_module_options_context(
|
||||||
&self,
|
&self,
|
||||||
_context: ModuleOptionsContextVc,
|
_context: Vc<ModuleOptionsContext>,
|
||||||
) -> ModuleOptionsContextVc {
|
) -> Vc<ModuleOptionsContext> {
|
||||||
self.client_module_options_context
|
self.client_module_options_context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_resolve_options_context(
|
fn process_resolve_options_context(
|
||||||
&self,
|
&self,
|
||||||
_context: ResolveOptionsContextVc,
|
_context: Vc<ResolveOptionsContext>,
|
||||||
) -> ResolveOptionsContextVc {
|
) -> Vc<ResolveOptionsContext> {
|
||||||
self.client_resolve_options_context
|
self.client_resolve_options_context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn process_module(
|
async fn process_module(
|
||||||
&self,
|
&self,
|
||||||
asset: ModuleVc,
|
asset: Vc<Box<dyn Module>>,
|
||||||
_context: ModuleAssetContextVc,
|
_context: Vc<ModuleAssetContext>,
|
||||||
) -> Result<ModuleVc> {
|
) -> Result<Vc<Box<dyn Module>>> {
|
||||||
Ok(
|
Ok(
|
||||||
if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? {
|
if let Some(placeable) =
|
||||||
WithChunksAssetVc::new(placeable, self.client_chunking_context).into()
|
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(asset).await?
|
||||||
|
{
|
||||||
|
Vc::upcast(WithChunksAsset::new(
|
||||||
|
placeable,
|
||||||
|
self.client_chunking_context,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
asset
|
asset
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,48 +1,44 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use turbo_tasks::{primitives::StringVc, Value};
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetContentVc, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
chunk::{
|
chunk::{availability_info::AvailabilityInfo, Chunk, ChunkableModule, ChunkingContext},
|
||||||
availability_info::AvailabilityInfo, ChunkVc, ChunkableModule, ChunkableModuleVc,
|
ident::AssetIdent,
|
||||||
ChunkingContextVc,
|
module::Module,
|
||||||
},
|
reference::AssetReferences,
|
||||||
ident::AssetIdentVc,
|
|
||||||
module::{Module, ModuleVc},
|
|
||||||
reference::AssetReferencesVc,
|
|
||||||
},
|
},
|
||||||
ecmascript::chunk::EcmascriptChunkingContextVc,
|
ecmascript::chunk::EcmascriptChunkingContext,
|
||||||
turbopack::ecmascript::chunk::{
|
turbopack::ecmascript::chunk::{
|
||||||
EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc,
|
EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkPlaceable, EcmascriptExports,
|
||||||
EcmascriptChunkVc, EcmascriptExportsVc,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn modifier() -> StringVc {
|
fn modifier() -> Vc<String> {
|
||||||
StringVc::cell("in chunking context".to_string())
|
Vc::cell("in chunking context".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct InChunkingContextAsset {
|
pub struct InChunkingContextAsset {
|
||||||
pub asset: EcmascriptChunkPlaceableVc,
|
pub asset: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
pub chunking_context: ChunkingContextVc,
|
pub chunking_context: Vc<Box<dyn ChunkingContext>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Asset for InChunkingContextAsset {
|
impl Asset for InChunkingContextAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ident(&self) -> AssetIdentVc {
|
fn ident(&self) -> Vc<AssetIdent> {
|
||||||
self.asset.ident().with_modifier(modifier())
|
self.asset.ident().with_modifier(modifier())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn content(&self) -> AssetContentVc {
|
fn content(&self) -> Vc<AssetContent> {
|
||||||
self.asset.content()
|
self.asset.content()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn references(&self) -> AssetReferencesVc {
|
fn references(&self) -> Vc<AssetReferences> {
|
||||||
self.asset.references()
|
self.asset.references()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,10 +51,14 @@ impl ChunkableModule for InChunkingContextAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn as_chunk(
|
fn as_chunk(
|
||||||
&self,
|
&self,
|
||||||
_context: ChunkingContextVc,
|
_context: Vc<Box<dyn ChunkingContext>>,
|
||||||
availability_info: Value<AvailabilityInfo>,
|
availability_info: Value<AvailabilityInfo>,
|
||||||
) -> ChunkVc {
|
) -> Vc<Box<dyn Chunk>> {
|
||||||
EcmascriptChunkVc::new(self.chunking_context, self.asset, availability_info).into()
|
Vc::upcast(EcmascriptChunk::new(
|
||||||
|
self.chunking_context,
|
||||||
|
self.asset,
|
||||||
|
availability_info,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,10 +67,11 @@ impl EcmascriptChunkPlaceable for InChunkingContextAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn as_chunk_item(
|
async fn as_chunk_item(
|
||||||
&self,
|
&self,
|
||||||
_context: EcmascriptChunkingContextVc,
|
_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
) -> Result<EcmascriptChunkItemVc> {
|
) -> Result<Vc<Box<dyn EcmascriptChunkItem>>> {
|
||||||
let Some(chunking_context) =
|
let Some(chunking_context) =
|
||||||
EcmascriptChunkingContextVc::resolve_from(&self.chunking_context).await?
|
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkingContext>>(self.chunking_context)
|
||||||
|
.await?
|
||||||
else {
|
else {
|
||||||
bail!("chunking context is not an EcmascriptChunkingContext")
|
bail!("chunking context is not an EcmascriptChunkingContext")
|
||||||
};
|
};
|
||||||
|
@ -78,7 +79,7 @@ impl EcmascriptChunkPlaceable for InChunkingContextAsset {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn get_exports(&self) -> EcmascriptExportsVc {
|
fn get_exports(&self) -> Vc<EcmascriptExports> {
|
||||||
self.asset.get_exports()
|
self.asset.get_exports()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,4 +2,4 @@ pub(crate) mod client_chunks_transition;
|
||||||
pub(crate) mod in_chunking_context_asset;
|
pub(crate) mod in_chunking_context_asset;
|
||||||
pub(crate) mod with_chunks;
|
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 anyhow::Result;
|
||||||
use indoc::writedoc;
|
use indoc::writedoc;
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{
|
turbo::{
|
||||||
tasks::{primitives::StringVc, TryJoinIterExt, Value},
|
tasks::{TryJoinIterExt, Value},
|
||||||
tasks_fs::rope::RopeBuilder,
|
tasks_fs::rope::RopeBuilder,
|
||||||
},
|
},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetContentVc, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
chunk::{
|
chunk::{
|
||||||
availability_info::AvailabilityInfo, ChunkDataVc, ChunkGroupReferenceVc, ChunkItem,
|
availability_info::AvailabilityInfo, Chunk, ChunkData, ChunkGroupReference,
|
||||||
ChunkItemVc, ChunkVc, ChunkableModule, ChunkableModuleVc, ChunkingContext,
|
ChunkItem, ChunkableModule, ChunkingContext, ChunksData,
|
||||||
ChunkingContextVc, ChunksDataVc,
|
|
||||||
},
|
},
|
||||||
ident::AssetIdentVc,
|
ident::AssetIdent,
|
||||||
module::{Module, ModuleVc},
|
module::Module,
|
||||||
output::OutputAssetsVc,
|
output::OutputAssets,
|
||||||
reference::AssetReferencesVc,
|
reference::AssetReferences,
|
||||||
},
|
},
|
||||||
ecmascript::{
|
ecmascript::{
|
||||||
chunk::{
|
chunk::{
|
||||||
EcmascriptChunkData, EcmascriptChunkItem, EcmascriptChunkItemContent,
|
EcmascriptChunk, EcmascriptChunkData, EcmascriptChunkItem,
|
||||||
EcmascriptChunkItemContentVc, EcmascriptChunkItemVc, EcmascriptChunkPlaceable,
|
EcmascriptChunkItemContent, EcmascriptChunkItemExt, EcmascriptChunkPlaceable,
|
||||||
EcmascriptChunkPlaceableVc, EcmascriptChunkVc, EcmascriptChunkingContextVc,
|
EcmascriptChunkingContext, EcmascriptExports,
|
||||||
EcmascriptExports, EcmascriptExportsVc,
|
|
||||||
},
|
},
|
||||||
utils::StringifyJs,
|
utils::StringifyJs,
|
||||||
},
|
},
|
||||||
|
@ -33,18 +32,18 @@ use turbopack_binding::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn modifier() -> StringVc {
|
fn modifier() -> Vc<String> {
|
||||||
StringVc::cell("chunks".to_string())
|
Vc::cell("chunks".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub struct WithChunksAsset {
|
pub struct WithChunksAsset {
|
||||||
asset: EcmascriptChunkPlaceableVc,
|
asset: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
chunking_context: EcmascriptChunkingContextVc,
|
chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl WithChunksAssetVc {
|
impl WithChunksAsset {
|
||||||
/// Create a new [`WithChunksAsset`].
|
/// Create a new [`WithChunksAsset`].
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
@ -53,23 +52,23 @@ impl WithChunksAssetVc {
|
||||||
/// * `chunking_context` - The chunking context of the asset.
|
/// * `chunking_context` - The chunking context of the asset.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
asset: EcmascriptChunkPlaceableVc,
|
asset: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
chunking_context: EcmascriptChunkingContextVc,
|
chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
) -> WithChunksAssetVc {
|
) -> Vc<WithChunksAsset> {
|
||||||
WithChunksAssetVc::cell(WithChunksAsset {
|
WithChunksAsset::cell(WithChunksAsset {
|
||||||
asset,
|
asset,
|
||||||
chunking_context,
|
chunking_context,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
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]
|
#[turbo_tasks::function]
|
||||||
async fn chunks(self) -> Result<OutputAssetsVc> {
|
async fn chunks(self: Vc<Self>) -> Result<Vc<OutputAssets>> {
|
||||||
let this = self.await?;
|
let this = self.await?;
|
||||||
Ok(this.chunking_context.chunk_group(self.entry_chunk()))
|
Ok(this.chunking_context.chunk_group(self.entry_chunk()))
|
||||||
}
|
}
|
||||||
|
@ -78,25 +77,24 @@ impl WithChunksAssetVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Asset for WithChunksAsset {
|
impl Asset for WithChunksAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ident(&self) -> AssetIdentVc {
|
fn ident(&self) -> Vc<AssetIdent> {
|
||||||
self.asset.ident().with_modifier(modifier())
|
self.asset.ident().with_modifier(modifier())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn content(&self) -> AssetContentVc {
|
fn content(&self) -> Vc<AssetContent> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn references(self_vc: WithChunksAssetVc) -> Result<AssetReferencesVc> {
|
async fn references(self: Vc<Self>) -> Result<Vc<AssetReferences>> {
|
||||||
let this = self_vc.await?;
|
let this = self.await?;
|
||||||
let entry_chunk = self_vc.entry_chunk();
|
let entry_chunk = self.entry_chunk();
|
||||||
|
|
||||||
Ok(AssetReferencesVc::cell(vec![ChunkGroupReferenceVc::new(
|
Ok(Vc::cell(vec![Vc::upcast(ChunkGroupReference::new(
|
||||||
this.chunking_context.into(),
|
Vc::upcast(this.chunking_context),
|
||||||
entry_chunk,
|
entry_chunk,
|
||||||
)
|
))]))
|
||||||
.into()]))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,16 +105,15 @@ impl Module for WithChunksAsset {}
|
||||||
impl ChunkableModule for WithChunksAsset {
|
impl ChunkableModule for WithChunksAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn as_chunk(
|
fn as_chunk(
|
||||||
self_vc: WithChunksAssetVc,
|
self: Vc<Self>,
|
||||||
context: ChunkingContextVc,
|
context: Vc<Box<dyn ChunkingContext>>,
|
||||||
availability_info: Value<AvailabilityInfo>,
|
availability_info: Value<AvailabilityInfo>,
|
||||||
) -> ChunkVc {
|
) -> Vc<Box<dyn Chunk>> {
|
||||||
EcmascriptChunkVc::new(
|
Vc::upcast(EcmascriptChunk::new(
|
||||||
context,
|
context,
|
||||||
self_vc.as_ecmascript_chunk_placeable(),
|
Vc::upcast(self),
|
||||||
availability_info,
|
availability_info,
|
||||||
)
|
))
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,19 +121,20 @@ impl ChunkableModule for WithChunksAsset {
|
||||||
impl EcmascriptChunkPlaceable for WithChunksAsset {
|
impl EcmascriptChunkPlaceable for WithChunksAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn as_chunk_item(
|
async fn as_chunk_item(
|
||||||
self_vc: WithChunksAssetVc,
|
self: Vc<Self>,
|
||||||
context: EcmascriptChunkingContextVc,
|
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
) -> Result<EcmascriptChunkItemVc> {
|
) -> Result<Vc<Box<dyn EcmascriptChunkItem>>> {
|
||||||
Ok(WithChunksChunkItem {
|
Ok(Vc::upcast(
|
||||||
context,
|
WithChunksChunkItem {
|
||||||
inner: self_vc,
|
context,
|
||||||
}
|
inner: self,
|
||||||
.cell()
|
}
|
||||||
.into())
|
.cell(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn get_exports(&self) -> EcmascriptExportsVc {
|
fn get_exports(&self) -> Vc<EcmascriptExports> {
|
||||||
// TODO This should be EsmExports
|
// TODO This should be EsmExports
|
||||||
EcmascriptExports::Value.cell()
|
EcmascriptExports::Value.cell()
|
||||||
}
|
}
|
||||||
|
@ -144,17 +142,17 @@ impl EcmascriptChunkPlaceable for WithChunksAsset {
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct WithChunksChunkItem {
|
struct WithChunksChunkItem {
|
||||||
context: EcmascriptChunkingContextVc,
|
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
inner: WithChunksAssetVc,
|
inner: Vc<WithChunksAsset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl WithChunksChunkItemVc {
|
impl WithChunksChunkItem {
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let inner = this.inner.await?;
|
let inner = this.inner.await?;
|
||||||
Ok(ChunkDataVc::from_assets(
|
Ok(ChunkData::from_assets(
|
||||||
inner.chunking_context.output_root(),
|
inner.chunking_context.output_root(),
|
||||||
this.inner.chunks(),
|
this.inner.chunks(),
|
||||||
))
|
))
|
||||||
|
@ -164,16 +162,16 @@ impl WithChunksChunkItemVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl EcmascriptChunkItem for WithChunksChunkItem {
|
impl EcmascriptChunkItem for WithChunksChunkItem {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn chunking_context(&self) -> EcmascriptChunkingContextVc {
|
fn chunking_context(&self) -> Vc<Box<dyn EcmascriptChunkingContext>> {
|
||||||
self.context
|
self.context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn content(self_vc: WithChunksChunkItemVc) -> Result<EcmascriptChunkItemContentVc> {
|
async fn content(self: Vc<Self>) -> Result<Vc<EcmascriptChunkItemContent>> {
|
||||||
let this = self_vc.await?;
|
let this = self.await?;
|
||||||
let inner = this.inner.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 = chunks_data.iter().try_join().await?;
|
||||||
let chunks_data: Vec<_> = chunks_data
|
let chunks_data: Vec<_> = chunks_data
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -212,18 +210,18 @@ impl EcmascriptChunkItem for WithChunksChunkItem {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ChunkItem for WithChunksChunkItem {
|
impl ChunkItem for WithChunksChunkItem {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn asset_ident(&self) -> AssetIdentVc {
|
fn asset_ident(&self) -> Vc<AssetIdent> {
|
||||||
self.inner.ident()
|
self.inner.ident()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn references(self_vc: WithChunksChunkItemVc) -> Result<AssetReferencesVc> {
|
async fn references(self: Vc<Self>) -> Result<Vc<AssetReferences>> {
|
||||||
let mut references = self_vc.await?.inner.references().await?.clone_value();
|
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());
|
references.extend(chunk_data.references().await?.iter().copied());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(AssetReferencesVc::cell(references))
|
Ok(Vc::cell(references))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use indexmap::indexmap;
|
use indexmap::indexmap;
|
||||||
use turbo_tasks::Value;
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
context::AssetContext,
|
context::AssetContext,
|
||||||
module::ModuleVc,
|
module::Module,
|
||||||
reference_type::{EntryReferenceSubType, InnerAssetsVc, ReferenceType},
|
reference_type::{EntryReferenceSubType, ReferenceType},
|
||||||
source::SourceVc,
|
source::Source,
|
||||||
},
|
|
||||||
turbopack::{
|
|
||||||
transition::{Transition, TransitionVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
|
turbopack::{transition::Transition, ModuleAssetContext},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::embed_js::next_asset;
|
use crate::embed_js::next_asset;
|
||||||
|
@ -25,43 +22,47 @@ pub struct NextServerToClientTransition {
|
||||||
impl Transition for NextServerToClientTransition {
|
impl Transition for NextServerToClientTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn process(
|
async fn process(
|
||||||
self_vc: NextServerToClientTransitionVc,
|
self: Vc<Self>,
|
||||||
source: SourceVc,
|
source: Vc<Box<dyn Source>>,
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
_reference_type: Value<ReferenceType>,
|
_reference_type: Value<ReferenceType>,
|
||||||
) -> Result<ModuleVc> {
|
) -> Result<Vc<Box<dyn Module>>> {
|
||||||
let this = self_vc.await?;
|
let this = self.await?;
|
||||||
let context = self_vc.process_context(context);
|
let context = self.process_context(context);
|
||||||
let client_chunks = context.with_transition("next-client-chunks").process(
|
let client_chunks = context
|
||||||
source,
|
.with_transition("next-client-chunks".to_string())
|
||||||
Value::new(ReferenceType::Entry(
|
.process(
|
||||||
EntryReferenceSubType::AppClientComponent,
|
source,
|
||||||
)),
|
Value::new(ReferenceType::Entry(
|
||||||
);
|
EntryReferenceSubType::AppClientComponent,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(match this.ssr {
|
Ok(match this.ssr {
|
||||||
true => {
|
true => {
|
||||||
let internal_source = next_asset("entry/app/server-to-client-ssr.tsx");
|
let internal_source = next_asset("entry/app/server-to-client-ssr.tsx".to_string());
|
||||||
let client_module = context.with_transition("next-ssr-client-module").process(
|
let client_module = context
|
||||||
source,
|
.with_transition("next-ssr-client-module".to_string())
|
||||||
Value::new(ReferenceType::Entry(
|
.process(
|
||||||
EntryReferenceSubType::AppClientComponent,
|
source,
|
||||||
)),
|
Value::new(ReferenceType::Entry(
|
||||||
);
|
EntryReferenceSubType::AppClientComponent,
|
||||||
|
)),
|
||||||
|
);
|
||||||
context.process(
|
context.process(
|
||||||
internal_source,
|
internal_source,
|
||||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap! {
|
Value::new(ReferenceType::Internal(Vc::cell(indexmap! {
|
||||||
"CLIENT_MODULE".to_string() => client_module.into(),
|
"CLIENT_MODULE".to_string() => Vc::upcast(client_module),
|
||||||
"CLIENT_CHUNKS".to_string() => client_chunks.into(),
|
"CLIENT_CHUNKS".to_string() => Vc::upcast(client_chunks),
|
||||||
}))),
|
}))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
false => {
|
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(
|
context.process(
|
||||||
internal_source,
|
internal_source,
|
||||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap! {
|
Value::new(ReferenceType::Internal(Vc::cell(indexmap! {
|
||||||
"CLIENT_CHUNKS".to_string() => client_chunks.into(),
|
"CLIENT_CHUNKS".to_string() => Vc::upcast(client_chunks),
|
||||||
}))),
|
}))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{compile_time_info::CompileTimeInfoVc, module::ModuleVc},
|
core::{compile_time_info::CompileTimeInfo, module::Module},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
ecmascript::chunk::EcmascriptChunkPlaceable, module_options::ModuleOptionsContext,
|
||||||
module_options::ModuleOptionsContextVc,
|
resolve_options_context::ResolveOptionsContext, transition::Transition, ModuleAssetContext,
|
||||||
resolve_options_context::ResolveOptionsContextVc,
|
|
||||||
transition::{Transition, TransitionVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,9 +12,9 @@ use super::with_chunking_context_scope_asset::WithChunkingContextScopeAsset;
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextSSRClientModuleTransition {
|
pub struct NextSSRClientModuleTransition {
|
||||||
pub ssr_environment: CompileTimeInfoVc,
|
pub ssr_environment: Vc<CompileTimeInfo>,
|
||||||
pub ssr_module_options_context: ModuleOptionsContextVc,
|
pub ssr_module_options_context: Vc<ModuleOptionsContext>,
|
||||||
pub ssr_resolve_options_context: ResolveOptionsContextVc,
|
pub ssr_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
|
@ -24,41 +22,44 @@ impl Transition for NextSSRClientModuleTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_compile_time_info(
|
fn process_compile_time_info(
|
||||||
&self,
|
&self,
|
||||||
_compile_time_info: CompileTimeInfoVc,
|
_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
) -> CompileTimeInfoVc {
|
) -> Vc<CompileTimeInfo> {
|
||||||
self.ssr_environment
|
self.ssr_environment
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_module_options_context(
|
fn process_module_options_context(
|
||||||
&self,
|
&self,
|
||||||
_context: ModuleOptionsContextVc,
|
_context: Vc<ModuleOptionsContext>,
|
||||||
) -> ModuleOptionsContextVc {
|
) -> Vc<ModuleOptionsContext> {
|
||||||
self.ssr_module_options_context
|
self.ssr_module_options_context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_resolve_options_context(
|
fn process_resolve_options_context(
|
||||||
&self,
|
&self,
|
||||||
_context: ResolveOptionsContextVc,
|
_context: Vc<ResolveOptionsContext>,
|
||||||
) -> ResolveOptionsContextVc {
|
) -> Vc<ResolveOptionsContext> {
|
||||||
self.ssr_resolve_options_context
|
self.ssr_resolve_options_context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn process_module(
|
async fn process_module(
|
||||||
&self,
|
&self,
|
||||||
asset: ModuleVc,
|
asset: Vc<Box<dyn Module>>,
|
||||||
_context: ModuleAssetContextVc,
|
_context: Vc<ModuleAssetContext>,
|
||||||
) -> Result<ModuleVc> {
|
) -> Result<Vc<Box<dyn Module>>> {
|
||||||
Ok(
|
Ok(
|
||||||
if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? {
|
if let Some(placeable) =
|
||||||
WithChunkingContextScopeAsset {
|
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(asset).await?
|
||||||
asset: placeable,
|
{
|
||||||
layer: "ssr".to_string(),
|
Vc::upcast(
|
||||||
}
|
WithChunkingContextScopeAsset {
|
||||||
.cell()
|
asset: placeable,
|
||||||
.into()
|
layer: "ssr".to_string(),
|
||||||
|
}
|
||||||
|
.cell(),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
asset
|
asset
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,48 +1,44 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use turbo_tasks::{primitives::StringVc, Value};
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetContentVc, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
chunk::{
|
chunk::{availability_info::AvailabilityInfo, Chunk, ChunkableModule, ChunkingContext},
|
||||||
availability_info::AvailabilityInfo, ChunkVc, ChunkableModule, ChunkableModuleVc,
|
ident::AssetIdent,
|
||||||
ChunkingContext, ChunkingContextVc,
|
module::Module,
|
||||||
},
|
reference::AssetReferences,
|
||||||
ident::AssetIdentVc,
|
|
||||||
module::{Module, ModuleVc},
|
|
||||||
reference::AssetReferencesVc,
|
|
||||||
},
|
},
|
||||||
ecmascript::chunk::EcmascriptChunkingContextVc,
|
ecmascript::chunk::EcmascriptChunkingContext,
|
||||||
turbopack::ecmascript::chunk::{
|
turbopack::ecmascript::chunk::{
|
||||||
EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc,
|
EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkPlaceable, EcmascriptExports,
|
||||||
EcmascriptChunkVc, EcmascriptExportsVc,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn modifier() -> StringVc {
|
fn modifier() -> Vc<String> {
|
||||||
StringVc::cell("with chunking context scope".to_string())
|
Vc::cell("with chunking context scope".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct WithChunkingContextScopeAsset {
|
pub struct WithChunkingContextScopeAsset {
|
||||||
pub asset: EcmascriptChunkPlaceableVc,
|
pub asset: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
pub layer: String,
|
pub layer: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Asset for WithChunkingContextScopeAsset {
|
impl Asset for WithChunkingContextScopeAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ident(&self) -> AssetIdentVc {
|
fn ident(&self) -> Vc<AssetIdent> {
|
||||||
self.asset.ident().with_modifier(modifier())
|
self.asset.ident().with_modifier(modifier())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn content(&self) -> AssetContentVc {
|
fn content(&self) -> Vc<AssetContent> {
|
||||||
self.asset.content()
|
self.asset.content()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn references(&self) -> AssetReferencesVc {
|
fn references(&self) -> Vc<AssetReferences> {
|
||||||
self.asset.references()
|
self.asset.references()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,15 +51,14 @@ impl ChunkableModule for WithChunkingContextScopeAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn as_chunk(
|
fn as_chunk(
|
||||||
&self,
|
&self,
|
||||||
context: ChunkingContextVc,
|
context: Vc<Box<dyn ChunkingContext>>,
|
||||||
availability_info: Value<AvailabilityInfo>,
|
availability_info: Value<AvailabilityInfo>,
|
||||||
) -> ChunkVc {
|
) -> Vc<Box<dyn Chunk>> {
|
||||||
EcmascriptChunkVc::new(
|
Vc::upcast(EcmascriptChunk::new(
|
||||||
context.with_layer(&self.layer),
|
context.with_layer(self.layer.clone()),
|
||||||
self.asset,
|
self.asset,
|
||||||
availability_info,
|
availability_info,
|
||||||
)
|
))
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,20 +67,22 @@ impl EcmascriptChunkPlaceable for WithChunkingContextScopeAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn as_chunk_item(
|
async fn as_chunk_item(
|
||||||
&self,
|
&self,
|
||||||
context: EcmascriptChunkingContextVc,
|
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
) -> Result<EcmascriptChunkItemVc> {
|
) -> Result<Vc<Box<dyn EcmascriptChunkItem>>> {
|
||||||
Ok(self.asset.as_chunk_item(
|
Ok(self.asset.as_chunk_item(
|
||||||
EcmascriptChunkingContextVc::resolve_from(context.with_layer(&self.layer))
|
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkingContext>>(
|
||||||
.await?
|
context.with_layer(self.layer.clone()),
|
||||||
.context(
|
)
|
||||||
"ChunkingContextVc::with_layer should not return a different kind of chunking \
|
.await?
|
||||||
context",
|
.context(
|
||||||
)?,
|
"ChunkingContext::with_layer should not return a different kind of chunking \
|
||||||
|
context",
|
||||||
|
)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn get_exports(&self) -> EcmascriptExportsVc {
|
fn get_exports(&self) -> Vc<EcmascriptExports> {
|
||||||
self.asset.get_exports()
|
self.asset.get_exports()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,28 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value, ValueToString, ValueToStringVc};
|
use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::FileSystemPathVc,
|
turbo::tasks_fs::FileSystemPath,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetContentVc, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
chunk::{
|
chunk::{
|
||||||
availability_info::AvailabilityInfo, ChunkDataVc, ChunkItem, ChunkItemVc, ChunkVc,
|
availability_info::AvailabilityInfo, Chunk, ChunkData, ChunkItem, ChunkableModule,
|
||||||
ChunkableModule, ChunkableModuleReference, ChunkableModuleReferenceVc,
|
ChunkableModuleReference, ChunkingContext, ChunkingType, ChunkingTypeOption,
|
||||||
ChunkableModuleVc, ChunkingContext, ChunkingContextVc, ChunkingType,
|
ChunksData,
|
||||||
ChunkingTypeOptionVc, ChunksDataVc,
|
|
||||||
},
|
},
|
||||||
ident::AssetIdentVc,
|
ident::AssetIdent,
|
||||||
module::{Module, ModuleVc},
|
module::Module,
|
||||||
output::OutputAssetsVc,
|
output::OutputAssets,
|
||||||
proxied_asset::ProxiedAssetVc,
|
proxied_asset::ProxiedAsset,
|
||||||
reference::{
|
reference::{AssetReference, AssetReferences, SingleAssetReference},
|
||||||
AssetReference, AssetReferenceVc, AssetReferencesVc, SingleAssetReferenceVc,
|
resolve::ResolveResult,
|
||||||
},
|
|
||||||
resolve::{ResolveResult, ResolveResultVc},
|
|
||||||
},
|
},
|
||||||
ecmascript::chunk::EcmascriptChunkData,
|
ecmascript::chunk::{EcmascriptChunkData, EcmascriptChunkItemExt},
|
||||||
turbopack::ecmascript::{
|
turbopack::ecmascript::{
|
||||||
chunk::{
|
chunk::{
|
||||||
EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc,
|
EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkItemContent,
|
||||||
EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc,
|
EcmascriptChunkPlaceable, EcmascriptChunkingContext, EcmascriptExports,
|
||||||
EcmascriptChunkVc, EcmascriptChunkingContextVc, EcmascriptExports,
|
|
||||||
EcmascriptExportsVc,
|
|
||||||
},
|
},
|
||||||
utils::StringifyJs,
|
utils::StringifyJs,
|
||||||
},
|
},
|
||||||
|
@ -35,35 +30,36 @@ use turbopack_binding::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn modifier() -> StringVc {
|
fn modifier() -> Vc<String> {
|
||||||
StringVc::cell("client chunks".to_string())
|
Vc::cell("client chunks".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct WithClientChunksAsset {
|
pub struct WithClientChunksAsset {
|
||||||
pub asset: EcmascriptChunkPlaceableVc,
|
pub asset: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
pub server_root: FileSystemPathVc,
|
pub server_root: Vc<FileSystemPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Asset for WithClientChunksAsset {
|
impl Asset for WithClientChunksAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ident(&self) -> AssetIdentVc {
|
fn ident(&self) -> Vc<AssetIdent> {
|
||||||
self.asset.ident().with_modifier(modifier())
|
self.asset.ident().with_modifier(modifier())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn content(&self) -> AssetContentVc {
|
fn content(&self) -> Vc<AssetContent> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn references(&self) -> AssetReferencesVc {
|
fn references(&self) -> Vc<AssetReferences> {
|
||||||
AssetReferencesVc::cell(vec![WithClientChunksAssetReference {
|
Vc::cell(vec![Vc::upcast(
|
||||||
asset: self.asset.into(),
|
WithClientChunksAssetReference {
|
||||||
}
|
asset: Vc::upcast(self.asset),
|
||||||
.cell()
|
}
|
||||||
.into()])
|
.cell(),
|
||||||
|
)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,16 +70,15 @@ impl Module for WithClientChunksAsset {}
|
||||||
impl ChunkableModule for WithClientChunksAsset {
|
impl ChunkableModule for WithClientChunksAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn as_chunk(
|
fn as_chunk(
|
||||||
self_vc: WithClientChunksAssetVc,
|
self: Vc<Self>,
|
||||||
context: ChunkingContextVc,
|
context: Vc<Box<dyn ChunkingContext>>,
|
||||||
availability_info: Value<AvailabilityInfo>,
|
availability_info: Value<AvailabilityInfo>,
|
||||||
) -> ChunkVc {
|
) -> Vc<Box<dyn Chunk>> {
|
||||||
EcmascriptChunkVc::new(
|
Vc::upcast(EcmascriptChunk::new(
|
||||||
context.with_layer("rsc"),
|
context.with_layer("rsc".to_string()),
|
||||||
self_vc.as_ecmascript_chunk_placeable(),
|
Vc::upcast(self),
|
||||||
availability_info,
|
availability_info,
|
||||||
)
|
))
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,24 +86,27 @@ impl ChunkableModule for WithClientChunksAsset {
|
||||||
impl EcmascriptChunkPlaceable for WithClientChunksAsset {
|
impl EcmascriptChunkPlaceable for WithClientChunksAsset {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn as_chunk_item(
|
async fn as_chunk_item(
|
||||||
self_vc: WithClientChunksAssetVc,
|
self: Vc<Self>,
|
||||||
context: EcmascriptChunkingContextVc,
|
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
) -> Result<EcmascriptChunkItemVc> {
|
) -> Result<Vc<Box<dyn EcmascriptChunkItem>>> {
|
||||||
Ok(WithClientChunksChunkItem {
|
Ok(Vc::upcast(
|
||||||
context: EcmascriptChunkingContextVc::resolve_from(context.with_layer("rsc"))
|
WithClientChunksChunkItem {
|
||||||
|
context: Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkingContext>>(
|
||||||
|
context.with_layer("rsc".to_string()),
|
||||||
|
)
|
||||||
.await?
|
.await?
|
||||||
.context(
|
.context(
|
||||||
"ChunkingContextVc::with_layer should not return a different kind of chunking \
|
"ChunkingContext::with_layer should not return a different kind of chunking \
|
||||||
context",
|
context",
|
||||||
)?,
|
)?,
|
||||||
inner: self_vc,
|
inner: self,
|
||||||
}
|
}
|
||||||
.cell()
|
.cell(),
|
||||||
.into())
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn get_exports(&self) -> EcmascriptExportsVc {
|
fn get_exports(&self) -> Vc<EcmascriptExports> {
|
||||||
// TODO This should be EsmExports
|
// TODO This should be EsmExports
|
||||||
EcmascriptExports::Value.cell()
|
EcmascriptExports::Value.cell()
|
||||||
}
|
}
|
||||||
|
@ -116,23 +114,23 @@ impl EcmascriptChunkPlaceable for WithClientChunksAsset {
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct WithClientChunksChunkItem {
|
struct WithClientChunksChunkItem {
|
||||||
context: EcmascriptChunkingContextVc,
|
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
inner: WithClientChunksAssetVc,
|
inner: Vc<WithClientChunksAsset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl WithClientChunksChunkItemVc {
|
impl WithClientChunksChunkItem {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn chunks(self) -> Result<OutputAssetsVc> {
|
async fn chunks(self: Vc<Self>) -> Result<Vc<OutputAssets>> {
|
||||||
let this = self.await?;
|
let this = self.await?;
|
||||||
let inner = this.inner.await?;
|
let inner = this.inner.await?;
|
||||||
Ok(this
|
Ok(this
|
||||||
.context
|
.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]
|
#[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 this = self.await?;
|
||||||
let inner = this.inner.await?;
|
let inner = this.inner.await?;
|
||||||
let chunks = self.chunks();
|
let chunks = self.chunks();
|
||||||
|
@ -144,21 +142,22 @@ impl WithClientChunksChunkItemVc {
|
||||||
// Only expose CSS chunks as client chunks.
|
// Only expose CSS chunks as client chunks.
|
||||||
if &*extension == "css" {
|
if &*extension == "css" {
|
||||||
if let Some(path) = output_root.get_path_to(&*chunk.ident().path().await?) {
|
if let Some(path) = output_root.get_path_to(&*chunk.ident().path().await?) {
|
||||||
client_chunks.push(
|
client_chunks.push(Vc::upcast(ProxiedAsset::new(
|
||||||
ProxiedAssetVc::new(chunk.into(), inner.server_root.join(path)).into(),
|
Vc::upcast(chunk),
|
||||||
);
|
inner.server_root.join(path.to_string()),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(OutputAssetsVc::cell(client_chunks))
|
Ok(Vc::cell(client_chunks))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let inner = this.inner.await?;
|
let inner = this.inner.await?;
|
||||||
Ok(ChunkDataVc::from_assets(
|
Ok(ChunkData::from_assets(
|
||||||
inner.server_root,
|
inner.server_root,
|
||||||
self.client_chunks(),
|
self.client_chunks(),
|
||||||
))
|
))
|
||||||
|
@ -168,16 +167,16 @@ impl WithClientChunksChunkItemVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl EcmascriptChunkItem for WithClientChunksChunkItem {
|
impl EcmascriptChunkItem for WithClientChunksChunkItem {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn chunking_context(&self) -> EcmascriptChunkingContextVc {
|
fn chunking_context(&self) -> Vc<Box<dyn EcmascriptChunkingContext>> {
|
||||||
self.context
|
self.context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn content(self_vc: WithClientChunksChunkItemVc) -> Result<EcmascriptChunkItemContentVc> {
|
async fn content(self: Vc<Self>) -> Result<Vc<EcmascriptChunkItemContent>> {
|
||||||
let this = self_vc.await?;
|
let this = self.await?;
|
||||||
let inner = this.inner.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 = chunks_data.iter().try_join().await?;
|
||||||
let chunks_data: Vec<_> = chunks_data
|
let chunks_data: Vec<_> = chunks_data
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -209,45 +208,47 @@ impl EcmascriptChunkItem for WithClientChunksChunkItem {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ChunkItem for WithClientChunksChunkItem {
|
impl ChunkItem for WithClientChunksChunkItem {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn asset_ident(&self) -> AssetIdentVc {
|
fn asset_ident(&self) -> Vc<AssetIdent> {
|
||||||
self.inner.ident()
|
self.inner.ident()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn references(self_vc: WithClientChunksChunkItemVc) -> Result<AssetReferencesVc> {
|
async fn references(self: Vc<Self>) -> Result<Vc<AssetReferences>> {
|
||||||
let this = self_vc.await?;
|
let this = self.await?;
|
||||||
let inner = this.inner.await?;
|
let inner = this.inner.await?;
|
||||||
let mut references = Vec::new();
|
let mut references = Vec::new();
|
||||||
references.push(
|
references.push(Vc::upcast(
|
||||||
WithClientChunksAssetReference {
|
WithClientChunksAssetReference {
|
||||||
asset: inner.asset.into(),
|
asset: Vc::upcast(inner.asset),
|
||||||
}
|
}
|
||||||
.cell()
|
.cell(),
|
||||||
.into(),
|
));
|
||||||
);
|
let client_chunks = self.client_chunks();
|
||||||
let client_chunks = self_vc.client_chunks();
|
|
||||||
let client_chunks = client_chunks.await?;
|
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() {
|
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());
|
references.extend(chunk_data.references().await?.iter().copied());
|
||||||
}
|
}
|
||||||
Ok(AssetReferencesVc::cell(references))
|
Ok(Vc::cell(references))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct WithClientChunksAssetReference {
|
struct WithClientChunksAssetReference {
|
||||||
asset: AssetVc,
|
asset: Vc<Box<dyn Asset>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ValueToString for WithClientChunksAssetReference {
|
impl ValueToString for WithClientChunksAssetReference {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn to_string(&self) -> Result<StringVc> {
|
async fn to_string(&self) -> Result<Vc<String>> {
|
||||||
Ok(StringVc::cell(format!(
|
Ok(Vc::cell(format!(
|
||||||
"local asset {}",
|
"local asset {}",
|
||||||
self.asset.ident().to_string().await?
|
self.asset.ident().to_string().await?
|
||||||
)))
|
)))
|
||||||
|
@ -257,7 +258,7 @@ impl ValueToString for WithClientChunksAssetReference {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl AssetReference for WithClientChunksAssetReference {
|
impl AssetReference for WithClientChunksAssetReference {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn resolve_reference(&self) -> ResolveResultVc {
|
fn resolve_reference(&self) -> Vc<ResolveResult> {
|
||||||
ResolveResult::asset(self.asset).cell()
|
ResolveResult::asset(self.asset).cell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,7 +266,7 @@ impl AssetReference for WithClientChunksAssetReference {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ChunkableModuleReference for WithClientChunksAssetReference {
|
impl ChunkableModuleReference for WithClientChunksAssetReference {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn chunking_type(&self) -> ChunkingTypeOptionVc {
|
fn chunking_type(&self) -> Vc<ChunkingTypeOption> {
|
||||||
ChunkingTypeOptionVc::cell(Some(ChunkingType::IsolatedParallel))
|
Vc::cell(Some(ChunkingType::IsolatedParallel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,63 +1,65 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use turbo_tasks::primitives::StringVc;
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetContentVc, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
ident::AssetIdentVc,
|
ident::AssetIdent,
|
||||||
module::{Module, ModuleVc},
|
module::Module,
|
||||||
reference::AssetReferencesVc,
|
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
|
/// A [`CssClientReferenceModule`] is a marker module used to indicate which
|
||||||
/// client reference should appear in the client reference manifest.
|
/// client reference should appear in the client reference manifest.
|
||||||
#[turbo_tasks::value(transparent)]
|
#[turbo_tasks::value(transparent)]
|
||||||
pub struct CssClientReferenceModule {
|
pub struct CssClientReferenceModule {
|
||||||
pub client_module: CssChunkPlaceableVc,
|
pub client_module: Vc<Box<dyn CssChunkPlaceable>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl CssClientReferenceModuleVc {
|
impl CssClientReferenceModule {
|
||||||
/// Create a new [`CssClientReferenceModule`] from the given source CSS
|
/// Create a new [`CssClientReferenceModule`] from the given source CSS
|
||||||
/// module.
|
/// module.
|
||||||
#[turbo_tasks::function]
|
#[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()
|
CssClientReferenceModule { client_module }.cell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn css_client_reference_modifier() -> StringVc {
|
fn css_client_reference_modifier() -> Vc<String> {
|
||||||
StringVc::cell("css client reference".to_string())
|
Vc::cell("css client reference".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Asset for CssClientReferenceModule {
|
impl Asset for CssClientReferenceModule {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ident(&self) -> AssetIdentVc {
|
fn ident(&self) -> Vc<AssetIdent> {
|
||||||
self.client_module
|
self.client_module
|
||||||
.ident()
|
.ident()
|
||||||
.with_modifier(css_client_reference_modifier())
|
.with_modifier(css_client_reference_modifier())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn content(&self) -> Result<AssetContentVc> {
|
fn content(&self) -> Result<Vc<AssetContent>> {
|
||||||
// The client reference asset only serves as a marker asset.
|
// The client reference asset only serves as a marker asset.
|
||||||
bail!("CssClientReferenceModule has no content")
|
bail!("CssClientReferenceModule has no content")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn references(_self_vc: CssClientReferenceModuleVc) -> AssetReferencesVc {
|
fn references(self: Vc<Self>) -> Vc<AssetReferences> {
|
||||||
AssetReferencesVc::empty()
|
AssetReferences::empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ParseCss for CssClientReferenceModule {
|
impl ParseCss for CssClientReferenceModule {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn parse_css(&self) -> Result<ParseCssResultVc> {
|
async fn parse_css(&self) -> Result<Vc<ParseCssResult>> {
|
||||||
let Some(parse_css) = ParseCssVc::resolve_from(self.client_module).await? else {
|
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");
|
bail!("CSS client reference client module must be CSS parseable");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,33 +1,31 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use turbo_tasks::Value;
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
module::ModuleVc,
|
module::Module,
|
||||||
reference_type::{CssReferenceSubType, ReferenceType},
|
reference_type::{CssReferenceSubType, ReferenceType},
|
||||||
resolve::ModulePartVc,
|
resolve::ModulePart,
|
||||||
source::SourceVc,
|
source::Source,
|
||||||
},
|
},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
css::chunk::CssChunkPlaceableVc,
|
css::chunk::CssChunkPlaceable, module_options::CustomModuleType, transition::Transition,
|
||||||
module_options::{CustomModuleType, CustomModuleTypeVc},
|
ModuleAssetContext,
|
||||||
transition::{Transition, TransitionVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
/// 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.
|
/// asset processing and inject a client reference on the server side.
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub struct CssClientReferenceModuleType {
|
pub struct CssClientReferenceModuleType {
|
||||||
client_transition: TransitionVc,
|
client_transition: Vc<Box<dyn Transition>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl CssClientReferenceModuleTypeVc {
|
impl CssClientReferenceModuleType {
|
||||||
#[turbo_tasks::function]
|
#[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()
|
CssClientReferenceModuleType { client_transition }.cell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,20 +35,22 @@ impl CustomModuleType for CssClientReferenceModuleType {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn create_module(
|
async fn create_module(
|
||||||
&self,
|
&self,
|
||||||
source: SourceVc,
|
source: Vc<Box<dyn Source>>,
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
_part: Option<ModulePartVc>,
|
_part: Option<Vc<ModulePart>>,
|
||||||
) -> Result<ModuleVc> {
|
) -> Result<Vc<Box<dyn Module>>> {
|
||||||
let client_module = self.client_transition.process(
|
let client_module = self.client_transition.process(
|
||||||
source,
|
source,
|
||||||
context,
|
context,
|
||||||
Value::new(ReferenceType::Css(CssReferenceSubType::Internal)),
|
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");
|
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::{
|
use turbopack_binding::turbopack::{
|
||||||
core::reference_type::{CssReferenceSubType, ReferenceType},
|
core::reference_type::{CssReferenceSubType, ReferenceType},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
module_options::{ModuleRule, ModuleRuleCondition, ModuleRuleEffect, ModuleType},
|
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(
|
pub(crate) fn get_next_css_client_reference_transforms_rule(
|
||||||
client_transition: TransitionVc,
|
client_transition: Vc<Box<dyn Transition>>,
|
||||||
) -> ModuleRule {
|
) -> ModuleRule {
|
||||||
let module_type = CssClientReferenceModuleTypeVc::new(client_transition);
|
let module_type = CssClientReferenceModuleType::new(client_transition);
|
||||||
|
|
||||||
ModuleRule::new_internal(
|
ModuleRule::new_internal(
|
||||||
// Override the default module type for CSS assets. Instead, they will go through the
|
// 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),
|
ReferenceType::Css(CssReferenceSubType::Internal),
|
||||||
)]),
|
)]),
|
||||||
vec![ModuleRuleEffect::ModuleType(ModuleType::Custom(
|
vec![ModuleRuleEffect::ModuleType(ModuleType::Custom(
|
||||||
module_type.into(),
|
Vc::upcast(module_type),
|
||||||
))],
|
))],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use turbo_tasks::primitives::StringVc;
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetContentVc, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
ident::AssetIdentVc,
|
ident::AssetIdent,
|
||||||
module::{Module, ModuleVc},
|
module::Module,
|
||||||
reference::AssetReferencesVc,
|
reference::AssetReferences,
|
||||||
},
|
},
|
||||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
ecmascript::chunk::EcmascriptChunkPlaceable,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An [`EcmascriptClientReferenceModule`] is a marker module, used by the
|
/// An [`EcmascriptClientReferenceModule`] is a marker module, used by the
|
||||||
|
@ -15,13 +15,13 @@ use turbopack_binding::turbopack::{
|
||||||
/// should appear in the client reference manifest.
|
/// should appear in the client reference manifest.
|
||||||
#[turbo_tasks::value(transparent)]
|
#[turbo_tasks::value(transparent)]
|
||||||
pub struct EcmascriptClientReferenceModule {
|
pub struct EcmascriptClientReferenceModule {
|
||||||
pub server_ident: AssetIdentVc,
|
pub server_ident: Vc<AssetIdent>,
|
||||||
pub client_module: EcmascriptChunkPlaceableVc,
|
pub client_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
pub ssr_module: EcmascriptChunkPlaceableVc,
|
pub ssr_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl EcmascriptClientReferenceModuleVc {
|
impl EcmascriptClientReferenceModule {
|
||||||
/// Create a new [`EcmascriptClientReferenceModule`].
|
/// Create a new [`EcmascriptClientReferenceModule`].
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
@ -32,10 +32,10 @@ impl EcmascriptClientReferenceModuleVc {
|
||||||
/// * `ssr_module` - The SSR module.
|
/// * `ssr_module` - The SSR module.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
server_ident: AssetIdentVc,
|
server_ident: Vc<AssetIdent>,
|
||||||
client_module: EcmascriptChunkPlaceableVc,
|
client_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
ssr_module: EcmascriptChunkPlaceableVc,
|
ssr_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
) -> EcmascriptClientReferenceModuleVc {
|
) -> Vc<EcmascriptClientReferenceModule> {
|
||||||
EcmascriptClientReferenceModule {
|
EcmascriptClientReferenceModule {
|
||||||
server_ident,
|
server_ident,
|
||||||
client_module,
|
client_module,
|
||||||
|
@ -46,27 +46,27 @@ impl EcmascriptClientReferenceModuleVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ecmascript_client_reference_modifier() -> StringVc {
|
fn ecmascript_client_reference_modifier() -> Vc<String> {
|
||||||
StringVc::cell("ecmascript client reference".to_string())
|
Vc::cell("ecmascript client reference".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Asset for EcmascriptClientReferenceModule {
|
impl Asset for EcmascriptClientReferenceModule {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ident(&self) -> AssetIdentVc {
|
fn ident(&self) -> Vc<AssetIdent> {
|
||||||
self.server_ident
|
self.server_ident
|
||||||
.with_modifier(ecmascript_client_reference_modifier())
|
.with_modifier(ecmascript_client_reference_modifier())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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.
|
// The ES client reference asset only serves as a marker asset.
|
||||||
bail!("EcmascriptClientReferenceModule has no content")
|
bail!("EcmascriptClientReferenceModule has no content")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn references(_self_vc: EcmascriptClientReferenceModuleVc) -> AssetReferencesVc {
|
fn references(self: Vc<Self>) -> Vc<AssetReferences> {
|
||||||
AssetReferencesVc::empty()
|
AssetReferences::empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,48 +2,46 @@ use std::{io::Write, iter::once};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use indoc::writedoc;
|
use indoc::writedoc;
|
||||||
use turbo_tasks::{primitives::StringVc, Value, ValueToString};
|
use turbo_tasks::{Value, ValueToString, Vc};
|
||||||
use turbo_tasks_fs::File;
|
use turbo_tasks_fs::File;
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetContentVc, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
chunk::{
|
chunk::{
|
||||||
availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableModule,
|
availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableModule, ChunkingContext,
|
||||||
ChunkableModuleVc, ChunkingContextVc,
|
|
||||||
},
|
},
|
||||||
code_builder::CodeBuilder,
|
code_builder::CodeBuilder,
|
||||||
context::{AssetContext, AssetContextVc},
|
context::AssetContext,
|
||||||
ident::AssetIdentVc,
|
ident::AssetIdent,
|
||||||
module::{Module, ModuleVc},
|
module::Module,
|
||||||
reference::{AssetReferencesVc, SingleAssetReferenceVc},
|
reference::{AssetReferences, SingleAssetReference},
|
||||||
reference_type::ReferenceType,
|
reference_type::ReferenceType,
|
||||||
virtual_source::VirtualSourceVc,
|
virtual_source::VirtualSource,
|
||||||
},
|
},
|
||||||
ecmascript::{
|
ecmascript::{
|
||||||
chunk::{
|
chunk::{
|
||||||
EcmascriptChunkItem, EcmascriptChunkItemContentVc, EcmascriptChunkItemVc,
|
EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkItemContent,
|
||||||
EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkVc,
|
EcmascriptChunkPlaceable, EcmascriptChunkingContext, EcmascriptExports,
|
||||||
EcmascriptChunkingContextVc, EcmascriptExportsVc,
|
|
||||||
},
|
},
|
||||||
utils::StringifyJs,
|
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 [`EcmascriptClientReferenceProxyModule`] is used in RSC to represent
|
||||||
/// a client or SSR asset.
|
/// a client or SSR asset.
|
||||||
#[turbo_tasks::value(transparent)]
|
#[turbo_tasks::value(transparent)]
|
||||||
pub struct EcmascriptClientReferenceProxyModule {
|
pub struct EcmascriptClientReferenceProxyModule {
|
||||||
server_module_ident: AssetIdentVc,
|
server_module_ident: Vc<AssetIdent>,
|
||||||
server_asset_context: AssetContextVc,
|
server_asset_context: Vc<Box<dyn AssetContext>>,
|
||||||
client_module: EcmascriptChunkPlaceableVc,
|
client_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
ssr_module: EcmascriptChunkPlaceableVc,
|
ssr_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl EcmascriptClientReferenceProxyModuleVc {
|
impl EcmascriptClientReferenceProxyModule {
|
||||||
/// Create a new [`EcmascriptClientReferenceProxyModule`].
|
/// Create a new [`EcmascriptClientReferenceProxyModule`].
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
@ -54,11 +52,11 @@ impl EcmascriptClientReferenceProxyModuleVc {
|
||||||
/// * `ssr_module` - The SSR module.
|
/// * `ssr_module` - The SSR module.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
server_module_ident: AssetIdentVc,
|
server_module_ident: Vc<AssetIdent>,
|
||||||
server_asset_context: AssetContextVc,
|
server_asset_context: Vc<Box<dyn AssetContext>>,
|
||||||
client_module: EcmascriptChunkPlaceableVc,
|
client_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
ssr_module: EcmascriptChunkPlaceableVc,
|
ssr_module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
) -> EcmascriptClientReferenceProxyModuleVc {
|
) -> Vc<EcmascriptClientReferenceProxyModule> {
|
||||||
EcmascriptClientReferenceProxyModule {
|
EcmascriptClientReferenceProxyModule {
|
||||||
server_module_ident,
|
server_module_ident,
|
||||||
server_asset_context,
|
server_asset_context,
|
||||||
|
@ -69,7 +67,7 @@ impl EcmascriptClientReferenceProxyModuleVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let mut code = CodeBuilder::default();
|
let mut code = CodeBuilder::default();
|
||||||
|
|
||||||
|
@ -96,18 +94,21 @@ impl EcmascriptClientReferenceProxyModuleVc {
|
||||||
|
|
||||||
let code = code.build();
|
let code = code.build();
|
||||||
let proxy_module_asset_content =
|
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(
|
let proxy_source = VirtualSource::new(
|
||||||
this.server_module_ident.path().join("proxy.ts"),
|
this.server_module_ident.path().join("proxy.ts".to_string()),
|
||||||
proxy_module_asset_content,
|
proxy_module_asset_content,
|
||||||
);
|
);
|
||||||
|
|
||||||
let proxy_module = this
|
let proxy_module = this.server_asset_context.process(
|
||||||
.server_asset_context
|
Vc::upcast(proxy_source),
|
||||||
.process(proxy_source.into(), Value::new(ReferenceType::Undefined));
|
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");
|
bail!("proxy asset is not an ecmascript module");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,48 +119,42 @@ impl EcmascriptClientReferenceProxyModuleVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Asset for EcmascriptClientReferenceProxyModule {
|
impl Asset for EcmascriptClientReferenceProxyModule {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ident(&self) -> AssetIdentVc {
|
fn ident(&self) -> Vc<AssetIdent> {
|
||||||
self.server_module_ident
|
self.server_module_ident
|
||||||
.with_modifier(client_proxy_modifier())
|
.with_modifier(client_proxy_modifier())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn content(&self) -> Result<AssetContentVc> {
|
fn content(&self) -> Result<Vc<AssetContent>> {
|
||||||
bail!("proxy module asset has no content")
|
bail!("proxy module asset has no content")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn references(
|
async fn references(self: Vc<Self>) -> Result<Vc<AssetReferences>> {
|
||||||
self_vc: EcmascriptClientReferenceProxyModuleVc,
|
|
||||||
) -> Result<AssetReferencesVc> {
|
|
||||||
let EcmascriptClientReferenceProxyModule {
|
let EcmascriptClientReferenceProxyModule {
|
||||||
server_module_ident,
|
server_module_ident,
|
||||||
server_asset_context: _,
|
server_asset_context: _,
|
||||||
client_module,
|
client_module,
|
||||||
ssr_module,
|
ssr_module,
|
||||||
} = &*self_vc.await?;
|
} = &*self.await?;
|
||||||
|
|
||||||
let references: Vec<_> = self_vc
|
let references: Vec<_> = self
|
||||||
.proxy_module_asset()
|
.proxy_module_asset()
|
||||||
.references()
|
.references()
|
||||||
.await?
|
.await?
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.chain(once(
|
.chain(once(Vc::upcast(SingleAssetReference::new(
|
||||||
SingleAssetReferenceVc::new(
|
Vc::upcast(EcmascriptClientReferenceModule::new(
|
||||||
EcmascriptClientReferenceModuleVc::new(
|
*server_module_ident,
|
||||||
*server_module_ident,
|
*client_module,
|
||||||
*client_module,
|
*ssr_module,
|
||||||
*ssr_module,
|
)),
|
||||||
)
|
client_reference_description(),
|
||||||
.into(),
|
))))
|
||||||
client_reference_description(),
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
))
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(AssetReferencesVc::cell(references))
|
Ok(Vc::cell(references))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,16 +165,15 @@ impl Module for EcmascriptClientReferenceProxyModule {}
|
||||||
impl ChunkableModule for EcmascriptClientReferenceProxyModule {
|
impl ChunkableModule for EcmascriptClientReferenceProxyModule {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn as_chunk(
|
fn as_chunk(
|
||||||
self_vc: EcmascriptClientReferenceProxyModuleVc,
|
self: Vc<Self>,
|
||||||
context: ChunkingContextVc,
|
context: Vc<Box<dyn ChunkingContext>>,
|
||||||
availability_info: Value<AvailabilityInfo>,
|
availability_info: Value<AvailabilityInfo>,
|
||||||
) -> ChunkVc {
|
) -> Vc<Box<dyn Chunk>> {
|
||||||
EcmascriptChunkVc::new(
|
Vc::upcast(EcmascriptChunk::new(
|
||||||
context,
|
context,
|
||||||
self_vc.as_ecmascript_chunk_placeable(),
|
Vc::upcast(self),
|
||||||
availability_info,
|
availability_info,
|
||||||
)
|
))
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,56 +181,57 @@ impl ChunkableModule for EcmascriptClientReferenceProxyModule {
|
||||||
impl EcmascriptChunkPlaceable for EcmascriptClientReferenceProxyModule {
|
impl EcmascriptChunkPlaceable for EcmascriptClientReferenceProxyModule {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn as_chunk_item(
|
fn as_chunk_item(
|
||||||
self_vc: EcmascriptClientReferenceProxyModuleVc,
|
self: Vc<Self>,
|
||||||
chunking_context: EcmascriptChunkingContextVc,
|
chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
) -> EcmascriptChunkItemVc {
|
) -> Vc<Box<dyn EcmascriptChunkItem>> {
|
||||||
ProxyModuleChunkItem {
|
Vc::upcast(
|
||||||
client_proxy_asset: self_vc,
|
ProxyModuleChunkItem {
|
||||||
inner_proxy_module_chunk_item: self_vc
|
client_proxy_asset: self,
|
||||||
.proxy_module_asset()
|
inner_proxy_module_chunk_item: self
|
||||||
.as_chunk_item(chunking_context),
|
.proxy_module_asset()
|
||||||
chunking_context,
|
.as_chunk_item(chunking_context),
|
||||||
}
|
chunking_context,
|
||||||
.cell()
|
}
|
||||||
.into()
|
.cell(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn get_exports(self_vc: EcmascriptClientReferenceProxyModuleVc) -> EcmascriptExportsVc {
|
fn get_exports(self: Vc<Self>) -> Vc<EcmascriptExports> {
|
||||||
self_vc.proxy_module_asset().get_exports()
|
self.proxy_module_asset().get_exports()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This wrapper only exists to overwrite the `asset_ident` method of the
|
/// This wrapper only exists to overwrite the `asset_ident` method of the
|
||||||
/// wrapped [`EcmascriptChunkItemVc`]. Otherwise, the asset ident of the
|
/// wrapped [`Vc<Box<dyn EcmascriptChunkItem>>`]. Otherwise, the asset ident of
|
||||||
/// chunk item would not be the same as the asset ident of the
|
/// the chunk item would not be the same as the asset ident of the
|
||||||
/// [`EcmascriptClientReferenceProxyModuleVc`].
|
/// [`Vc<EcmascriptClientReferenceProxyModule>`].
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct ProxyModuleChunkItem {
|
struct ProxyModuleChunkItem {
|
||||||
client_proxy_asset: EcmascriptClientReferenceProxyModuleVc,
|
client_proxy_asset: Vc<EcmascriptClientReferenceProxyModule>,
|
||||||
inner_proxy_module_chunk_item: EcmascriptChunkItemVc,
|
inner_proxy_module_chunk_item: Vc<Box<dyn EcmascriptChunkItem>>,
|
||||||
chunking_context: EcmascriptChunkingContextVc,
|
chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn client_proxy_modifier() -> StringVc {
|
fn client_proxy_modifier() -> Vc<String> {
|
||||||
StringVc::cell("client proxy".to_string())
|
Vc::cell("client proxy".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn client_reference_description() -> StringVc {
|
fn client_reference_description() -> Vc<String> {
|
||||||
StringVc::cell("client references".to_string())
|
Vc::cell("client references".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ChunkItem for ProxyModuleChunkItem {
|
impl ChunkItem for ProxyModuleChunkItem {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn asset_ident(&self) -> AssetIdentVc {
|
async fn asset_ident(&self) -> Vc<AssetIdent> {
|
||||||
self.client_proxy_asset.ident()
|
self.client_proxy_asset.ident()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn references(&self) -> AssetReferencesVc {
|
fn references(&self) -> Vc<AssetReferences> {
|
||||||
self.client_proxy_asset.references()
|
self.client_proxy_asset.references()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,7 +239,7 @@ impl ChunkItem for ProxyModuleChunkItem {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl EcmascriptChunkItem for ProxyModuleChunkItem {
|
impl EcmascriptChunkItem for ProxyModuleChunkItem {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn content(&self) -> EcmascriptChunkItemContentVc {
|
fn content(&self) -> Vc<EcmascriptChunkItemContent> {
|
||||||
self.inner_proxy_module_chunk_item.content()
|
self.inner_proxy_module_chunk_item.content()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,13 +247,13 @@ impl EcmascriptChunkItem for ProxyModuleChunkItem {
|
||||||
fn content_with_availability_info(
|
fn content_with_availability_info(
|
||||||
&self,
|
&self,
|
||||||
availability_info: Value<AvailabilityInfo>,
|
availability_info: Value<AvailabilityInfo>,
|
||||||
) -> EcmascriptChunkItemContentVc {
|
) -> Vc<EcmascriptChunkItemContent> {
|
||||||
self.inner_proxy_module_chunk_item
|
self.inner_proxy_module_chunk_item
|
||||||
.content_with_availability_info(availability_info)
|
.content_with_availability_info(availability_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn chunking_context(&self) -> EcmascriptChunkingContextVc {
|
fn chunking_context(&self) -> Vc<Box<dyn EcmascriptChunkingContext>> {
|
||||||
self.inner_proxy_module_chunk_item.chunking_context()
|
self.inner_proxy_module_chunk_item.chunking_context()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use turbo_tasks::Value;
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::Asset,
|
asset::Asset,
|
||||||
module::ModuleVc,
|
module::Module,
|
||||||
reference_type::{EntryReferenceSubType, ReferenceType},
|
reference_type::{EntryReferenceSubType, ReferenceType},
|
||||||
source::SourceVc,
|
source::Source,
|
||||||
},
|
},
|
||||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
ecmascript::chunk::EcmascriptChunkPlaceable,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
transition::{ContextTransitionVc, Transition, TransitionVc},
|
transition::{ContextTransition, Transition},
|
||||||
ModuleAssetContextVc,
|
ModuleAssetContext,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::ecmascript_client_reference_proxy_module::EcmascriptClientReferenceProxyModuleVc;
|
use super::ecmascript_client_reference_proxy_module::EcmascriptClientReferenceProxyModule;
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextEcmascriptClientReferenceTransition {
|
pub struct NextEcmascriptClientReferenceTransition {
|
||||||
client_transition: ContextTransitionVc,
|
client_transition: Vc<ContextTransition>,
|
||||||
ssr_transition: ContextTransitionVc,
|
ssr_transition: Vc<ContextTransition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextEcmascriptClientReferenceTransitionVc {
|
impl NextEcmascriptClientReferenceTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
client_transition: ContextTransitionVc,
|
client_transition: Vc<ContextTransition>,
|
||||||
ssr_transition: ContextTransitionVc,
|
ssr_transition: Vc<ContextTransition>,
|
||||||
) -> Self {
|
) -> Vc<Self> {
|
||||||
NextEcmascriptClientReferenceTransition {
|
NextEcmascriptClientReferenceTransition {
|
||||||
client_transition,
|
client_transition,
|
||||||
ssr_transition,
|
ssr_transition,
|
||||||
|
@ -42,10 +42,10 @@ impl Transition for NextEcmascriptClientReferenceTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn process(
|
async fn process(
|
||||||
&self,
|
&self,
|
||||||
source: SourceVc,
|
source: Vc<Box<dyn Source>>,
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
_reference_type: Value<ReferenceType>,
|
_reference_type: Value<ReferenceType>,
|
||||||
) -> Result<ModuleVc> {
|
) -> Result<Vc<Box<dyn Module>>> {
|
||||||
let client_module = self.client_transition.process(
|
let client_module = self.client_transition.process(
|
||||||
source,
|
source,
|
||||||
context,
|
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 {
|
else {
|
||||||
bail!("client asset is not ecmascript chunk placeable");
|
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");
|
bail!("SSR asset is not ecmascript chunk placeable");
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO(alexkirsz) This is necessary to remove the transition currently set on
|
// TODO(alexkirsz) This is necessary to remove the transition currently set on
|
||||||
// the context.
|
// the context.
|
||||||
let context = context.await?;
|
let context = context.await?;
|
||||||
let server_context = ModuleAssetContextVc::new(
|
let server_context = ModuleAssetContext::new(
|
||||||
context.transitions,
|
context.transitions,
|
||||||
context.compile_time_info,
|
context.compile_time_info,
|
||||||
context.module_options_context,
|
context.module_options_context,
|
||||||
context.resolve_options_context,
|
context.resolve_options_context,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(EcmascriptClientReferenceProxyModuleVc::new(
|
Ok(Vc::upcast(EcmascriptClientReferenceProxyModule::new(
|
||||||
source.ident(),
|
source.ident(),
|
||||||
server_context.into(),
|
Vc::upcast(server_context),
|
||||||
client_module,
|
client_module,
|
||||||
ssr_module,
|
ssr_module,
|
||||||
)
|
)))
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,9 @@ pub(crate) mod css_client_reference;
|
||||||
pub(crate) mod ecmascript_client_reference;
|
pub(crate) mod ecmascript_client_reference;
|
||||||
pub(crate) mod visit_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::{
|
pub use ecmascript_client_reference::{
|
||||||
ecmascript_client_reference_module::EcmascriptClientReferenceModuleVc,
|
ecmascript_client_reference_module::EcmascriptClientReferenceModule,
|
||||||
ecmascript_client_reference_transition::NextEcmascriptClientReferenceTransitionVc,
|
ecmascript_client_reference_transition::NextEcmascriptClientReferenceTransition,
|
||||||
};
|
|
||||||
pub use visit_client_reference::{
|
|
||||||
ClientReference, ClientReferenceType, ClientReferencesByEntry, ClientReferencesByEntryVc,
|
|
||||||
};
|
};
|
||||||
|
pub use visit_client_reference::{ClientReference, ClientReferenceType, ClientReferencesByEntry};
|
||||||
|
|
|
@ -7,29 +7,29 @@ use turbo_tasks::{
|
||||||
debug::ValueDebugFormat,
|
debug::ValueDebugFormat,
|
||||||
graph::{AdjacencyMap, GraphTraversal, Visit, VisitControlFlow},
|
graph::{AdjacencyMap, GraphTraversal, Visit, VisitControlFlow},
|
||||||
trace::TraceRawVcs,
|
trace::TraceRawVcs,
|
||||||
TryJoinIterExt,
|
TryJoinIterExt, Vc,
|
||||||
};
|
};
|
||||||
use turbopack_binding::turbopack::core::{
|
use turbopack_binding::turbopack::core::{
|
||||||
asset::{Asset, AssetVc, AssetsVc},
|
asset::{Asset, Assets},
|
||||||
reference::AssetReference,
|
reference::AssetReference,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
css_client_reference::css_client_reference_module::CssClientReferenceModuleVc,
|
css_client_reference::css_client_reference_module::CssClientReferenceModule,
|
||||||
ecmascript_client_reference::ecmascript_client_reference_module::EcmascriptClientReferenceModuleVc,
|
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(
|
#[derive(
|
||||||
Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ValueDebugFormat, TraceRawVcs,
|
Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ValueDebugFormat, TraceRawVcs,
|
||||||
)]
|
)]
|
||||||
pub struct ClientReference {
|
pub struct ClientReference {
|
||||||
server_component: Option<NextServerComponentModuleVc>,
|
server_component: Option<Vc<NextServerComponentModule>>,
|
||||||
ty: ClientReferenceType,
|
ty: ClientReferenceType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientReference {
|
impl ClientReference {
|
||||||
pub fn server_component(&self) -> Option<&NextServerComponentModuleVc> {
|
pub fn server_component(&self) -> Option<&Vc<NextServerComponentModule>> {
|
||||||
self.server_component.as_ref()
|
self.server_component.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,17 +42,17 @@ impl ClientReference {
|
||||||
Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ValueDebugFormat, TraceRawVcs,
|
Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ValueDebugFormat, TraceRawVcs,
|
||||||
)]
|
)]
|
||||||
pub enum ClientReferenceType {
|
pub enum ClientReferenceType {
|
||||||
EcmascriptClientReference(EcmascriptClientReferenceModuleVc),
|
EcmascriptClientReference(Vc<EcmascriptClientReferenceModule>),
|
||||||
CssClientReference(CssClientReferenceModuleVc),
|
CssClientReference(Vc<CssClientReferenceModule>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(transparent)]
|
#[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]
|
#[turbo_tasks::value_impl]
|
||||||
impl ClientReferencesByEntryVc {
|
impl ClientReferencesByEntry {
|
||||||
#[turbo_tasks::function]
|
#[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 entries = entries.await?;
|
||||||
|
|
||||||
let graph = AdjacencyMap::new()
|
let graph = AdjacencyMap::new()
|
||||||
|
@ -95,7 +95,7 @@ impl ClientReferencesByEntryVc {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(ClientReferencesByEntryVc::cell(client_references))
|
Ok(Vc::cell(client_references))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,14 +103,14 @@ struct VisitClientReference;
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||||
struct VisitClientReferenceNode {
|
struct VisitClientReferenceNode {
|
||||||
server_component: Option<NextServerComponentModuleVc>,
|
server_component: Option<Vc<NextServerComponentModule>>,
|
||||||
ty: VisitClientReferenceNodeType,
|
ty: VisitClientReferenceNodeType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||||
enum VisitClientReferenceNodeType {
|
enum VisitClientReferenceNodeType {
|
||||||
ClientReference(ClientReference),
|
ClientReference(ClientReference),
|
||||||
Internal(AssetVc),
|
Internal(Vc<Box<dyn Asset>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visit<VisitClientReferenceNode> for VisitClientReference {
|
impl Visit<VisitClientReferenceNode> for VisitClientReference {
|
||||||
|
@ -149,7 +149,8 @@ impl Visit<VisitClientReferenceNode> for VisitClientReference {
|
||||||
|
|
||||||
let referenced_assets = referenced_assets.map(|asset| async move {
|
let referenced_assets = referenced_assets.map(|asset| async move {
|
||||||
if let Some(client_reference_asset) =
|
if let Some(client_reference_asset) =
|
||||||
EcmascriptClientReferenceModuleVc::resolve_from(asset).await?
|
Vc::try_resolve_downcast_type::<EcmascriptClientReferenceModule>(asset)
|
||||||
|
.await?
|
||||||
{
|
{
|
||||||
return Ok(VisitClientReferenceNode {
|
return Ok(VisitClientReferenceNode {
|
||||||
server_component: node.server_component,
|
server_component: node.server_component,
|
||||||
|
@ -165,7 +166,7 @@ impl Visit<VisitClientReferenceNode> for VisitClientReference {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(css_client_reference_asset) =
|
if let Some(css_client_reference_asset) =
|
||||||
CssClientReferenceModuleVc::resolve_from(asset).await?
|
Vc::try_resolve_downcast_type::<CssClientReferenceModule>(asset).await?
|
||||||
{
|
{
|
||||||
return Ok(VisitClientReferenceNode {
|
return Ok(VisitClientReferenceNode {
|
||||||
server_component: node.server_component,
|
server_component: node.server_component,
|
||||||
|
@ -181,7 +182,8 @@ impl Visit<VisitClientReferenceNode> for VisitClientReference {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(server_component_asset) =
|
if let Some(server_component_asset) =
|
||||||
NextServerComponentModuleVc::resolve_from(asset).await?
|
Vc::try_resolve_downcast_type::<NextServerComponentModule>(asset)
|
||||||
|
.await?
|
||||||
{
|
{
|
||||||
return Ok(VisitClientReferenceNode {
|
return Ok(VisitClientReferenceNode {
|
||||||
server_component: Some(server_component_asset),
|
server_component: Some(server_component_asset),
|
||||||
|
|
|
@ -2,28 +2,24 @@ use anyhow::{Context, Result};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{trace::TraceRawVcs, Completion, Value, Vc};
|
||||||
primitives::{BoolVc, JsonValueVc, StringVc, StringsVc},
|
|
||||||
trace::TraceRawVcs,
|
|
||||||
CompletionVc, Value,
|
|
||||||
};
|
|
||||||
use turbo_tasks_fs::json::parse_json_with_source_context;
|
use turbo_tasks_fs::json::parse_json_with_source_context;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{tasks_env::EnvMapVc, tasks_fs::FileSystemPathVc},
|
turbo::{tasks_env::EnvMap, tasks_fs::FileSystemPath},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::Asset,
|
asset::Asset,
|
||||||
changed::any_content_changed,
|
changed::any_content_changed,
|
||||||
chunk::ChunkingContext,
|
chunk::ChunkingContext,
|
||||||
context::AssetContext,
|
context::AssetContext,
|
||||||
file_source::FileSourceVc,
|
file_source::FileSource,
|
||||||
ident::AssetIdentVc,
|
ident::AssetIdent,
|
||||||
issue::{Issue, IssueContextExt, IssueSeverity, IssueSeverityVc, IssueVc},
|
issue::{Issue, IssueContextExt, IssueExt, IssueSeverity},
|
||||||
reference_type::{EntryReferenceSubType, InnerAssetsVc, ReferenceType},
|
reference_type::{EntryReferenceSubType, InnerAssets, ReferenceType},
|
||||||
resolve::{
|
resolve::{
|
||||||
find_context_file,
|
find_context_file,
|
||||||
options::{ImportMap, ImportMapping},
|
options::{ImportMap, ImportMapping},
|
||||||
FindContextFileResult, ResolveAliasMap, ResolveAliasMapVc,
|
FindContextFileResult, ResolveAliasMap,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ecmascript_plugin::transform::{
|
ecmascript_plugin::transform::{
|
||||||
|
@ -33,12 +29,12 @@ use turbopack_binding::{
|
||||||
node::{
|
node::{
|
||||||
debug::should_debug,
|
debug::should_debug,
|
||||||
evaluate::evaluate,
|
evaluate::evaluate,
|
||||||
execution_context::{ExecutionContext, ExecutionContextVc},
|
execution_context::ExecutionContext,
|
||||||
transforms::webpack::{WebpackLoaderItem, WebpackLoaderItemsVc},
|
transforms::webpack::{WebpackLoaderItem, WebpackLoaderItems},
|
||||||
},
|
},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
evaluate_context::node_evaluate_asset_context,
|
evaluate_context::node_evaluate_asset_context,
|
||||||
module_options::{LoaderRuleItem, OptionWebpackRulesVc, WebpackRulesVc},
|
module_options::{LoaderRuleItem, OptionWebpackRules},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -54,8 +50,8 @@ struct NextConfigAndCustomRoutesRaw {
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct NextConfigAndCustomRoutes {
|
struct NextConfigAndCustomRoutes {
|
||||||
config: NextConfigVc,
|
config: Vc<NextConfig>,
|
||||||
custom_routes: CustomRoutesVc,
|
custom_routes: Vc<CustomRoutes>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||||
|
@ -70,7 +66,7 @@ struct CustomRoutesRaw {
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct CustomRoutes {
|
struct CustomRoutes {
|
||||||
rewrites: RewritesVc,
|
rewrites: Vc<Rewrites>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(serialization = "custom", eq = "manual")]
|
#[turbo_tasks::value(serialization = "custom", eq = "manual")]
|
||||||
|
@ -510,17 +506,17 @@ pub enum RemoveConsoleConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextConfigVc {
|
impl NextConfig {
|
||||||
#[turbo_tasks::function]
|
#[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)
|
let config: NextConfig = serde_json::from_str(&s)
|
||||||
.with_context(|| format!("failed to parse next.config.js: {}", s))?;
|
.with_context(|| format!("failed to parse next.config.js: {}", s))?;
|
||||||
Ok(config.cell())
|
Ok(config.cell())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn server_component_externals(self) -> Result<StringsVc> {
|
pub async fn server_component_externals(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
|
||||||
Ok(StringsVc::cell(
|
Ok(Vc::cell(
|
||||||
self.await?
|
self.await?
|
||||||
.experimental
|
.experimental
|
||||||
.server_components_external_packages
|
.server_components_external_packages
|
||||||
|
@ -531,8 +527,8 @@ impl NextConfigVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn app_dir(self) -> Result<BoolVc> {
|
pub async fn app_dir(self: Vc<Self>) -> Result<Vc<bool>> {
|
||||||
Ok(BoolVc::cell(
|
Ok(Vc::cell(
|
||||||
self.await?
|
self.await?
|
||||||
.experimental
|
.experimental
|
||||||
.app_dir
|
.app_dir
|
||||||
|
@ -543,7 +539,7 @@ impl NextConfigVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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
|
// 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)
|
// 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.
|
// then stringifies it. We do the interop here as well.
|
||||||
|
@ -564,28 +560,28 @@ impl NextConfigVc {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(EnvMapVc::cell(env))
|
Ok(Vc::cell(env))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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())
|
Ok(self.await?.images.clone().cell())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn page_extensions(self) -> Result<StringsVc> {
|
pub async fn page_extensions(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
|
||||||
Ok(StringsVc::cell(self.await?.page_extensions.clone()))
|
Ok(Vc::cell(self.await?.page_extensions.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn transpile_packages(self) -> Result<StringsVc> {
|
pub async fn transpile_packages(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
|
||||||
Ok(StringsVc::cell(
|
Ok(Vc::cell(
|
||||||
self.await?.transpile_packages.clone().unwrap_or_default(),
|
self.await?.transpile_packages.clone().unwrap_or_default(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let Some(turbo_rules) = this
|
let Some(turbo_rules) = this
|
||||||
.experimental
|
.experimental
|
||||||
|
@ -593,15 +589,15 @@ impl NextConfigVc {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|t| t.rules.as_ref())
|
.and_then(|t| t.rules.as_ref())
|
||||||
else {
|
else {
|
||||||
return Ok(OptionWebpackRulesVc::cell(None));
|
return Ok(Vc::cell(None));
|
||||||
};
|
};
|
||||||
if turbo_rules.is_empty() {
|
if turbo_rules.is_empty() {
|
||||||
return Ok(OptionWebpackRulesVc::cell(None));
|
return Ok(Vc::cell(None));
|
||||||
}
|
}
|
||||||
let mut rules = IndexMap::new();
|
let mut rules = IndexMap::new();
|
||||||
for (ext, rule) in turbo_rules {
|
for (ext, rule) in turbo_rules {
|
||||||
fn transform_loaders(loaders: &[LoaderItem]) -> WebpackLoaderItemsVc {
|
fn transform_loaders(loaders: &[LoaderItem]) -> Vc<WebpackLoaderItems> {
|
||||||
WebpackLoaderItemsVc::cell(
|
Vc::cell(
|
||||||
loaders
|
loaders
|
||||||
.iter()
|
.iter()
|
||||||
.map(|item| match item {
|
.map(|item| match item {
|
||||||
|
@ -627,13 +623,11 @@ impl NextConfigVc {
|
||||||
|
|
||||||
rules.insert(ext.clone(), rule);
|
rules.insert(ext.clone(), rule);
|
||||||
}
|
}
|
||||||
Ok(OptionWebpackRulesVc::cell(Some(WebpackRulesVc::cell(
|
Ok(Vc::cell(Some(Vc::cell(rules))))
|
||||||
rules,
|
|
||||||
))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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 this = self.await?;
|
||||||
let Some(resolve_alias) = this
|
let Some(resolve_alias) = this
|
||||||
.experimental
|
.experimental
|
||||||
|
@ -641,29 +635,27 @@ impl NextConfigVc {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|t| t.resolve_alias.as_ref())
|
.and_then(|t| t.resolve_alias.as_ref())
|
||||||
else {
|
else {
|
||||||
return Ok(ResolveAliasMapVc::cell(ResolveAliasMap::default()));
|
return Ok(ResolveAliasMap::cell(ResolveAliasMap::default()));
|
||||||
};
|
};
|
||||||
let alias_map: ResolveAliasMap = resolve_alias.try_into()?;
|
let alias_map: ResolveAliasMap = resolve_alias.try_into()?;
|
||||||
Ok(alias_map.cell())
|
Ok(alias_map.cell())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn mdx_rs(self) -> Result<BoolVc> {
|
pub async fn mdx_rs(self: Vc<Self>) -> Result<Vc<bool>> {
|
||||||
Ok(BoolVc::cell(
|
Ok(Vc::cell(self.await?.experimental.mdx_rs.unwrap_or(false)))
|
||||||
self.await?.experimental.mdx_rs.unwrap_or(false),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn sass_config(self) -> Result<JsonValueVc> {
|
pub async fn sass_config(self: Vc<Self>) -> Result<Vc<JsonValue>> {
|
||||||
Ok(JsonValueVc::cell(
|
Ok(Vc::cell(
|
||||||
self.await?.sass_options.clone().unwrap_or_default(),
|
self.await?.sass_options.clone().unwrap_or_default(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_configs() -> StringsVc {
|
fn next_configs() -> Vc<Vec<String>> {
|
||||||
StringsVc::cell(
|
Vc::cell(
|
||||||
["next.config.mjs", "next.config.js"]
|
["next.config.mjs", "next.config.js"]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(ToOwned::to_owned)
|
.map(ToOwned::to_owned)
|
||||||
|
@ -672,14 +664,14 @@ fn next_configs() -> StringsVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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)
|
Ok(load_config_and_custom_routes(execution_context)
|
||||||
.await?
|
.await?
|
||||||
.config)
|
.config)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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)
|
Ok(load_config_and_custom_routes(execution_context)
|
||||||
.await?
|
.await?
|
||||||
.custom_routes
|
.custom_routes
|
||||||
|
@ -689,8 +681,8 @@ pub async fn load_rewrites(execution_context: ExecutionContextVc) -> Result<Rewr
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn load_config_and_custom_routes(
|
async fn load_config_and_custom_routes(
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
) -> Result<NextConfigAndCustomRoutesVc> {
|
) -> Result<Vc<NextConfigAndCustomRoutes>> {
|
||||||
let ExecutionContext { project_path, .. } = *execution_context.await?;
|
let ExecutionContext { project_path, .. } = *execution_context.await?;
|
||||||
let find_config_result = find_context_file(project_path, next_configs());
|
let find_config_result = find_context_file(project_path, next_configs());
|
||||||
let config_file = match &*find_config_result.await? {
|
let config_file = match &*find_config_result.await? {
|
||||||
|
@ -705,9 +697,9 @@ async fn load_config_and_custom_routes(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn load_next_config_and_custom_routes_internal(
|
async fn load_next_config_and_custom_routes_internal(
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
config_file: Option<FileSystemPathVc>,
|
config_file: Option<Vc<FileSystemPath>>,
|
||||||
) -> Result<NextConfigAndCustomRoutesVc> {
|
) -> Result<Vc<NextConfigAndCustomRoutes>> {
|
||||||
let ExecutionContext {
|
let ExecutionContext {
|
||||||
project_path,
|
project_path,
|
||||||
chunking_context,
|
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());
|
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 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
|
// This invalidates the execution when anything referenced by the config file
|
||||||
// changes
|
// changes
|
||||||
let config_asset = context.process(
|
let config_asset = context.process(
|
||||||
config_asset.into(),
|
Vc::upcast(config_asset),
|
||||||
Value::new(ReferenceType::Internal(InnerAssetsVc::empty())),
|
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(
|
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)),
|
Value::new(ReferenceType::Entry(EntryReferenceSubType::Undefined)),
|
||||||
);
|
);
|
||||||
let config_value = evaluate(
|
let config_value = evaluate(
|
||||||
load_next_config_asset.into(),
|
Vc::upcast(load_next_config_asset),
|
||||||
project_path,
|
project_path,
|
||||||
env,
|
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,
|
context,
|
||||||
chunking_context.with_layer("next_config"),
|
chunking_context.with_layer("next_config".to_string()),
|
||||||
None,
|
None,
|
||||||
vec![],
|
vec![],
|
||||||
config_changed,
|
config_changed,
|
||||||
|
@ -778,13 +770,12 @@ async fn load_next_config_and_custom_routes_internal(
|
||||||
path: config_file.unwrap_or(project_path),
|
path: config_file.unwrap_or(project_path),
|
||||||
old_name: "experimental.turbo.loaders".to_string(),
|
old_name: "experimental.turbo.loaders".to_string(),
|
||||||
new_name: "experimental.turbo.rules".to_string(),
|
new_name: "experimental.turbo.rules".to_string(),
|
||||||
description: "The new option is similar, but the key should be a glob instead of \
|
description: indoc::indoc! { r#"
|
||||||
an extension.
|
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\"] }"
|
Example: loaders: { ".mdx": ["mdx-loader"] } -> rules: { "*.mdx": ["mdx-loader"] }"# }
|
||||||
.to_string(),
|
.to_string(),
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
.as_issue()
|
|
||||||
.emit()
|
.emit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -800,8 +791,8 @@ Example: loaders: { \".mdx\": [\"mdx-loader\"] } -> rules: { \"*.mdx\": [\"mdx-l
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn has_next_config(context: FileSystemPathVc) -> Result<BoolVc> {
|
pub async fn has_next_config(context: Vc<FileSystemPath>) -> Result<Vc<bool>> {
|
||||||
Ok(BoolVc::cell(!matches!(
|
Ok(Vc::cell(!matches!(
|
||||||
*find_context_file(context, next_configs()).await?,
|
*find_context_file(context, next_configs()).await?,
|
||||||
FindContextFileResult::NotFound(_)
|
FindContextFileResult::NotFound(_)
|
||||||
)))
|
)))
|
||||||
|
@ -809,7 +800,7 @@ pub async fn has_next_config(context: FileSystemPathVc) -> Result<BoolVc> {
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct OutdatedConfigIssue {
|
struct OutdatedConfigIssue {
|
||||||
path: FileSystemPathVc,
|
path: Vc<FileSystemPath>,
|
||||||
old_name: String,
|
old_name: String,
|
||||||
new_name: String,
|
new_name: String,
|
||||||
description: String,
|
description: String,
|
||||||
|
@ -818,30 +809,30 @@ struct OutdatedConfigIssue {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Issue for OutdatedConfigIssue {
|
impl Issue for OutdatedConfigIssue {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn severity(&self) -> IssueSeverityVc {
|
fn severity(&self) -> Vc<IssueSeverity> {
|
||||||
IssueSeverity::Error.into()
|
IssueSeverity::Error.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn category(&self) -> StringVc {
|
fn category(&self) -> Vc<String> {
|
||||||
StringVc::cell("config".to_string())
|
Vc::cell("config".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn context(&self) -> FileSystemPathVc {
|
fn context(&self) -> Vc<FileSystemPath> {
|
||||||
self.path
|
self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn title(&self) -> StringVc {
|
fn title(&self) -> Vc<String> {
|
||||||
StringVc::cell(format!(
|
Vc::cell(format!(
|
||||||
"\"{}\" has been replaced by \"{}\"",
|
"\"{}\" has been replaced by \"{}\"",
|
||||||
self.old_name, self.new_name
|
self.old_name, self.new_name
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn description(&self) -> StringVc {
|
fn description(&self) -> Vc<String> {
|
||||||
StringVc::cell(self.description.to_string())
|
Vc::cell(self.description.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use turbo_tasks::primitives::StringVc;
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::turbopack::core::{
|
use turbopack_binding::turbopack::core::{
|
||||||
asset::{Asset, AssetContentVc, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
chunk::{ChunkableModule, ChunkableModuleVc, ChunkingContext, ChunkingContextVc},
|
chunk::{ChunkableModule, ChunkingContext},
|
||||||
ident::AssetIdentVc,
|
ident::AssetIdent,
|
||||||
module::{Module, ModuleVc},
|
module::Module,
|
||||||
output::OutputAssetsVc,
|
output::OutputAssets,
|
||||||
reference::AssetReferencesVc,
|
reference::AssetReferences,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A [`NextDynamicEntryModule`] is a marker asset used to indicate which
|
/// A [`NextDynamicEntryModule`] is a marker asset used to indicate which
|
||||||
/// dynamic assets should appear in the dynamic manifest.
|
/// dynamic assets should appear in the dynamic manifest.
|
||||||
#[turbo_tasks::value(transparent)]
|
#[turbo_tasks::value(transparent)]
|
||||||
pub struct NextDynamicEntryModule {
|
pub struct NextDynamicEntryModule {
|
||||||
pub client_entry_module: ModuleVc,
|
pub client_entry_module: Vc<Box<dyn Module>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextDynamicEntryModuleVc {
|
impl NextDynamicEntryModule {
|
||||||
/// Create a new [`NextDynamicEntryModule`] from the given source CSS
|
/// Create a new [`NextDynamicEntryModule`] from the given source CSS
|
||||||
/// asset.
|
/// asset.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(client_entry_module: ModuleVc) -> NextDynamicEntryModuleVc {
|
pub fn new(client_entry_module: Vc<Box<dyn Module>>) -> Vc<NextDynamicEntryModule> {
|
||||||
NextDynamicEntryModule {
|
NextDynamicEntryModule {
|
||||||
client_entry_module,
|
client_entry_module,
|
||||||
}
|
}
|
||||||
|
@ -30,13 +30,13 @@ impl NextDynamicEntryModuleVc {
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn client_chunks(
|
pub async fn client_chunks(
|
||||||
self,
|
self: Vc<Self>,
|
||||||
client_chunking_context: ChunkingContextVc,
|
client_chunking_context: Vc<Box<dyn ChunkingContext>>,
|
||||||
) -> Result<OutputAssetsVc> {
|
) -> Result<Vc<OutputAssets>> {
|
||||||
let this = self.await?;
|
let this = self.await?;
|
||||||
|
|
||||||
let Some(client_entry_module) =
|
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 {
|
else {
|
||||||
bail!("dynamic client asset must be chunkable");
|
bail!("dynamic client asset must be chunkable");
|
||||||
};
|
};
|
||||||
|
@ -47,28 +47,28 @@ impl NextDynamicEntryModuleVc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn dynamic_modifier() -> StringVc {
|
fn dynamic_modifier() -> Vc<String> {
|
||||||
StringVc::cell("dynamic".to_string())
|
Vc::cell("dynamic".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Asset for NextDynamicEntryModule {
|
impl Asset for NextDynamicEntryModule {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ident(&self) -> AssetIdentVc {
|
fn ident(&self) -> Vc<AssetIdent> {
|
||||||
self.client_entry_module
|
self.client_entry_module
|
||||||
.ident()
|
.ident()
|
||||||
.with_modifier(dynamic_modifier())
|
.with_modifier(dynamic_modifier())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn content(&self) -> Result<AssetContentVc> {
|
fn content(&self) -> Result<Vc<AssetContent>> {
|
||||||
// The client reference asset only serves as a marker asset.
|
// The client reference asset only serves as a marker asset.
|
||||||
bail!("NextDynamicEntryModule has no content")
|
bail!("NextDynamicEntryModule has no content")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn references(_self_vc: NextDynamicEntryModuleVc) -> AssetReferencesVc {
|
fn references(self: Vc<Self>) -> Vc<AssetReferences> {
|
||||||
AssetReferencesVc::empty()
|
AssetReferences::empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use turbo_tasks::Value;
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{module::ModuleVc, reference_type::ReferenceType, source::SourceVc},
|
core::{module::Module, reference_type::ReferenceType, source::Source},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
transition::{ContextTransitionVc, Transition, TransitionVc},
|
transition::{ContextTransition, Transition},
|
||||||
ModuleAssetContextVc,
|
ModuleAssetContext,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::NextDynamicEntryModuleVc;
|
use super::NextDynamicEntryModule;
|
||||||
|
|
||||||
/// This transition is used to create the marker asset for a next/dynamic
|
/// 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
|
/// import. This will get picked up during module processing and will be used to
|
||||||
/// create the dynamic entry, and the dynamic manifest entry.
|
/// create the dynamic entry, and the dynamic manifest entry.
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub struct NextDynamicTransition {
|
pub struct NextDynamicTransition {
|
||||||
client_transition: ContextTransitionVc,
|
client_transition: Vc<ContextTransition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextDynamicTransitionVc {
|
impl NextDynamicTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(client_transition: ContextTransitionVc) -> Self {
|
pub fn new(client_transition: Vc<ContextTransition>) -> Vc<Self> {
|
||||||
NextDynamicTransition { client_transition }.cell()
|
NextDynamicTransition { client_transition }.cell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,14 +31,14 @@ impl Transition for NextDynamicTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn process(
|
async fn process(
|
||||||
&self,
|
&self,
|
||||||
source: SourceVc,
|
source: Vc<Box<dyn Source>>,
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
_reference_type: Value<ReferenceType>,
|
_reference_type: Value<ReferenceType>,
|
||||||
) -> Result<ModuleVc> {
|
) -> Result<Vc<Box<dyn Module>>> {
|
||||||
let client_module =
|
let client_module =
|
||||||
self.client_transition
|
self.client_transition
|
||||||
.process(source, context, Value::new(ReferenceType::Undefined));
|
.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 dynamic_transition;
|
||||||
pub(crate) mod visit_dynamic;
|
pub(crate) mod visit_dynamic;
|
||||||
|
|
||||||
pub use dynamic_module::NextDynamicEntryModuleVc;
|
pub use dynamic_module::NextDynamicEntryModule;
|
||||||
pub use dynamic_transition::NextDynamicTransitionVc;
|
pub use dynamic_transition::NextDynamicTransition;
|
||||||
pub use visit_dynamic::NextDynamicEntriesVc;
|
pub use visit_dynamic::NextDynamicEntries;
|
||||||
|
|
|
@ -3,22 +3,22 @@ use std::future::Future;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{
|
||||||
graph::{AdjacencyMap, GraphTraversal, Visit, VisitControlFlow},
|
graph::{AdjacencyMap, GraphTraversal, Visit, VisitControlFlow},
|
||||||
TryJoinIterExt,
|
TryJoinIterExt, Vc,
|
||||||
};
|
};
|
||||||
use turbopack_binding::turbopack::core::{
|
use turbopack_binding::turbopack::core::{
|
||||||
asset::{Asset, AssetVc, AssetsVc},
|
asset::{Asset, Assets},
|
||||||
reference::AssetReference,
|
reference::AssetReference,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::NextDynamicEntryModuleVc;
|
use super::NextDynamicEntryModule;
|
||||||
|
|
||||||
#[turbo_tasks::value(transparent)]
|
#[turbo_tasks::value(transparent)]
|
||||||
pub struct NextDynamicEntries(Vec<NextDynamicEntryModuleVc>);
|
pub struct NextDynamicEntries(Vec<Vc<NextDynamicEntryModule>>);
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextDynamicEntriesVc {
|
impl NextDynamicEntries {
|
||||||
#[turbo_tasks::function]
|
#[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()
|
let nodes: Vec<_> = AdjacencyMap::new()
|
||||||
.skip_duplicates()
|
.skip_duplicates()
|
||||||
.visit(
|
.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)]
|
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||||
enum VisitDynamicNode {
|
enum VisitDynamicNode {
|
||||||
Dynamic(NextDynamicEntryModuleVc),
|
Dynamic(Vc<NextDynamicEntryModule>),
|
||||||
Internal(AssetVc),
|
Internal(Vc<Box<dyn Asset>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visit<VisitDynamicNode> for VisitDynamic {
|
impl Visit<VisitDynamicNode> for VisitDynamic {
|
||||||
|
@ -77,7 +77,7 @@ impl Visit<VisitDynamicNode> for VisitDynamic {
|
||||||
let node = node.clone();
|
let node = node.clone();
|
||||||
async move {
|
async move {
|
||||||
let asset = match node {
|
let asset = match node {
|
||||||
VisitDynamicNode::Dynamic(dynamic_asset) => dynamic_asset.into(),
|
VisitDynamicNode::Dynamic(dynamic_asset) => Vc::upcast(dynamic_asset),
|
||||||
VisitDynamicNode::Internal(asset) => asset,
|
VisitDynamicNode::Internal(asset) => asset,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ impl Visit<VisitDynamicNode> for VisitDynamic {
|
||||||
|
|
||||||
let referenced_assets = referenced_assets.map(|asset| async move {
|
let referenced_assets = referenced_assets.map(|asset| async move {
|
||||||
if let Some(next_dynamic_asset) =
|
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));
|
return Ok(VisitDynamicNode::Dynamic(next_dynamic_asset));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,25 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use turbo_tasks::Value;
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::FileSystemPathVc,
|
turbo::tasks_fs::FileSystemPath,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
compile_time_defines,
|
compile_time_defines,
|
||||||
compile_time_info::{
|
compile_time_info::{
|
||||||
CompileTimeDefines, CompileTimeDefinesVc, CompileTimeInfo, CompileTimeInfoVc,
|
CompileTimeDefines, CompileTimeInfo, FreeVarReference, FreeVarReferences,
|
||||||
FreeVarReference, FreeVarReferencesVc,
|
|
||||||
},
|
|
||||||
environment::{
|
|
||||||
EdgeWorkerEnvironment, EnvironmentVc, ExecutionEnvironment, ServerAddrVc,
|
|
||||||
},
|
},
|
||||||
|
environment::{EdgeWorkerEnvironment, Environment, ExecutionEnvironment, ServerAddr},
|
||||||
free_var_references,
|
free_var_references,
|
||||||
},
|
},
|
||||||
node::execution_context::ExecutionContextVc,
|
node::execution_context::ExecutionContext,
|
||||||
turbopack::resolve_options_context::{ResolveOptionsContext, ResolveOptionsContextVc},
|
turbopack::resolve_options_context::ResolveOptionsContext,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mode::NextMode, next_config::NextConfigVc, next_import_map::get_next_edge_import_map,
|
mode::NextMode, next_config::NextConfig, next_import_map::get_next_edge_import_map,
|
||||||
next_server::context::ServerContextType,
|
next_server::context::ServerContextType, next_shared::resolve::UnsupportedModulesResolvePlugin,
|
||||||
next_shared::resolve::UnsupportedModulesResolvePluginVc, util::foreign_code_context_condition,
|
util::foreign_code_context_condition,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn defines() -> CompileTimeDefines {
|
fn defines() -> CompileTimeDefines {
|
||||||
|
@ -37,12 +34,12 @@ fn defines() -> CompileTimeDefines {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn next_edge_defines() -> CompileTimeDefinesVc {
|
fn next_edge_defines() -> Vc<CompileTimeDefines> {
|
||||||
defines().cell()
|
defines().cell()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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!(
|
free_var_references!(
|
||||||
..defines().into_iter(),
|
..defines().into_iter(),
|
||||||
Buffer = FreeVarReference::EcmaScriptModule {
|
Buffer = FreeVarReference::EcmaScriptModule {
|
||||||
|
@ -61,10 +58,10 @@ fn next_edge_free_vars(project_path: FileSystemPathVc) -> FreeVarReferencesVc {
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn get_edge_compile_time_info(
|
pub fn get_edge_compile_time_info(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
server_addr: ServerAddrVc,
|
server_addr: Vc<ServerAddr>,
|
||||||
) -> CompileTimeInfoVc {
|
) -> Vc<CompileTimeInfo> {
|
||||||
CompileTimeInfo::builder(EnvironmentVc::new(Value::new(
|
CompileTimeInfo::builder(Environment::new(Value::new(
|
||||||
ExecutionEnvironment::EdgeWorker(EdgeWorkerEnvironment { server_addr }.into()),
|
ExecutionEnvironment::EdgeWorker(EdgeWorkerEnvironment { server_addr }.into()),
|
||||||
)))
|
)))
|
||||||
.defines(next_edge_defines())
|
.defines(next_edge_defines())
|
||||||
|
@ -74,12 +71,12 @@ pub fn get_edge_compile_time_info(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_edge_resolve_options_context(
|
pub async fn get_edge_resolve_options_context(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
ty: Value<ServerContextType>,
|
ty: Value<ServerContextType>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
) -> Result<ResolveOptionsContextVc> {
|
) -> Result<Vc<ResolveOptionsContext>> {
|
||||||
let next_edge_import_map =
|
let next_edge_import_map =
|
||||||
get_next_edge_import_map(project_path, ty, mode, next_config, execution_context);
|
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),
|
import_map: Some(next_edge_import_map),
|
||||||
module: true,
|
module: true,
|
||||||
browser: true,
|
browser: true,
|
||||||
plugins: vec![UnsupportedModulesResolvePluginVc::new(project_path).into()],
|
plugins: vec![Vc::upcast(UnsupportedModulesResolvePlugin::new(
|
||||||
|
project_path,
|
||||||
|
))],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,22 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use indexmap::indexmap;
|
use indexmap::indexmap;
|
||||||
use turbo_tasks::Value;
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::FileSystemPathVc,
|
turbo::tasks_fs::FileSystemPath,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
chunk::{ChunkableModuleVc, ChunkingContextVc},
|
chunk::{ChunkableModule, ChunkingContext},
|
||||||
compile_time_info::CompileTimeInfoVc,
|
compile_time_info::CompileTimeInfo,
|
||||||
context::AssetContext,
|
context::AssetContext,
|
||||||
file_source::FileSourceVc,
|
file_source::FileSource,
|
||||||
module::ModuleVc,
|
module::Module,
|
||||||
reference_type::{EcmaScriptModulesReferenceSubType, InnerAssetsVc, ReferenceType},
|
reference_type::{EcmaScriptModulesReferenceSubType, ReferenceType},
|
||||||
source::SourceVc,
|
source::Source,
|
||||||
},
|
},
|
||||||
ecmascript::chunk_group_files_asset::ChunkGroupFilesAsset,
|
ecmascript::chunk_group_files_asset::ChunkGroupFilesAsset,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
module_options::ModuleOptionsContextVc,
|
module_options::ModuleOptionsContext, resolve_options_context::ResolveOptionsContext,
|
||||||
resolve_options_context::ResolveOptionsContextVc,
|
transition::Transition, ModuleAssetContext,
|
||||||
transition::{Transition, TransitionVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -32,12 +30,12 @@ use crate::embed_js::next_js_file_path;
|
||||||
/// that for running them in the edge sandbox.
|
/// that for running them in the edge sandbox.
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextEdgePageTransition {
|
pub struct NextEdgePageTransition {
|
||||||
pub edge_compile_time_info: CompileTimeInfoVc,
|
pub edge_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
pub edge_chunking_context: ChunkingContextVc,
|
pub edge_chunking_context: Vc<Box<dyn ChunkingContext>>,
|
||||||
pub edge_module_options_context: Option<ModuleOptionsContextVc>,
|
pub edge_module_options_context: Option<Vc<ModuleOptionsContext>>,
|
||||||
pub edge_resolve_options_context: ResolveOptionsContextVc,
|
pub edge_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||||
pub output_path: FileSystemPathVc,
|
pub output_path: Vc<FileSystemPath>,
|
||||||
pub bootstrap_asset: SourceVc,
|
pub bootstrap_asset: Vc<Box<dyn Source>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
|
@ -45,47 +43,48 @@ impl Transition for NextEdgePageTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_compile_time_info(
|
fn process_compile_time_info(
|
||||||
&self,
|
&self,
|
||||||
_compile_time_info: CompileTimeInfoVc,
|
_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
) -> CompileTimeInfoVc {
|
) -> Vc<CompileTimeInfo> {
|
||||||
self.edge_compile_time_info
|
self.edge_compile_time_info
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_module_options_context(
|
fn process_module_options_context(
|
||||||
&self,
|
&self,
|
||||||
context: ModuleOptionsContextVc,
|
context: Vc<ModuleOptionsContext>,
|
||||||
) -> ModuleOptionsContextVc {
|
) -> Vc<ModuleOptionsContext> {
|
||||||
self.edge_module_options_context.unwrap_or(context)
|
self.edge_module_options_context.unwrap_or(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_resolve_options_context(
|
fn process_resolve_options_context(
|
||||||
&self,
|
&self,
|
||||||
_context: ResolveOptionsContextVc,
|
_context: Vc<ResolveOptionsContext>,
|
||||||
) -> ResolveOptionsContextVc {
|
) -> Vc<ResolveOptionsContext> {
|
||||||
self.edge_resolve_options_context
|
self.edge_resolve_options_context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn process_module(
|
async fn process_module(
|
||||||
&self,
|
&self,
|
||||||
asset: ModuleVc,
|
asset: Vc<Box<dyn Module>>,
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
) -> Result<ModuleVc> {
|
) -> Result<Vc<Box<dyn Module>>> {
|
||||||
let module = context.process(
|
let module = context.process(
|
||||||
self.bootstrap_asset,
|
self.bootstrap_asset,
|
||||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap! {
|
Value::new(ReferenceType::Internal(Vc::cell(indexmap! {
|
||||||
"APP_ENTRY".to_string() => asset.into(),
|
"APP_ENTRY".to_string() => Vc::upcast(asset),
|
||||||
"APP_BOOTSTRAP".to_string() => context.with_transition("next-client").process(
|
"APP_BOOTSTRAP".to_string() => Vc::upcast(context.with_transition("next-client".to_string()).process(
|
||||||
FileSourceVc::new(next_js_file_path("entry/app/hydrate.tsx")).into(),
|
Vc::upcast(FileSource::new(next_js_file_path("entry/app/hydrate.tsx".to_string()))),
|
||||||
Value::new(ReferenceType::EcmaScriptModules(
|
Value::new(ReferenceType::EcmaScriptModules(
|
||||||
EcmaScriptModulesReferenceSubType::Undefined,
|
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");
|
bail!("Internal module is not chunkable");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,6 +95,6 @@ impl Transition for NextEdgePageTransition {
|
||||||
runtime_entries: None,
|
runtime_entries: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(asset.cell().into())
|
Ok(Vc::upcast(asset.cell()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,32 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use indexmap::indexmap;
|
use indexmap::indexmap;
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::FileSystemPathVc,
|
turbo::tasks_fs::FileSystemPath,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
chunk::ChunkingContextVc, compile_time_info::CompileTimeInfoVc, module::ModuleVc,
|
chunk::ChunkingContext, compile_time_info::CompileTimeInfo, module::Module,
|
||||||
source::SourceVc,
|
source::Source,
|
||||||
},
|
},
|
||||||
ecmascript::chunk_group_files_asset::ChunkGroupFilesAsset,
|
ecmascript::chunk_group_files_asset::ChunkGroupFilesAsset,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
module_options::ModuleOptionsContextVc,
|
module_options::ModuleOptionsContext, resolve_options_context::ResolveOptionsContext,
|
||||||
resolve_options_context::ResolveOptionsContextVc,
|
transition::Transition, ModuleAssetContext,
|
||||||
transition::{Transition, TransitionVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::bootstrap::{route_bootstrap, BootstrapConfigVc};
|
use crate::bootstrap::route_bootstrap;
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextEdgeRouteTransition {
|
pub struct NextEdgeRouteTransition {
|
||||||
pub edge_compile_time_info: CompileTimeInfoVc,
|
pub edge_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
pub edge_chunking_context: ChunkingContextVc,
|
pub edge_chunking_context: Vc<Box<dyn ChunkingContext>>,
|
||||||
pub edge_module_options_context: Option<ModuleOptionsContextVc>,
|
pub edge_module_options_context: Option<Vc<ModuleOptionsContext>>,
|
||||||
pub edge_resolve_options_context: ResolveOptionsContextVc,
|
pub edge_resolve_options_context: Vc<ResolveOptionsContext>,
|
||||||
pub output_path: FileSystemPathVc,
|
pub output_path: Vc<FileSystemPath>,
|
||||||
pub base_path: FileSystemPathVc,
|
pub base_path: Vc<FileSystemPath>,
|
||||||
pub bootstrap_asset: SourceVc,
|
pub bootstrap_asset: Vc<Box<dyn Source>>,
|
||||||
pub entry_name: String,
|
pub entry_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,50 +35,50 @@ impl Transition for NextEdgeRouteTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_compile_time_info(
|
fn process_compile_time_info(
|
||||||
&self,
|
&self,
|
||||||
_compile_time_info: CompileTimeInfoVc,
|
_compile_time_info: Vc<CompileTimeInfo>,
|
||||||
) -> CompileTimeInfoVc {
|
) -> Vc<CompileTimeInfo> {
|
||||||
self.edge_compile_time_info
|
self.edge_compile_time_info
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_module_options_context(
|
fn process_module_options_context(
|
||||||
&self,
|
&self,
|
||||||
context: ModuleOptionsContextVc,
|
context: Vc<ModuleOptionsContext>,
|
||||||
) -> ModuleOptionsContextVc {
|
) -> Vc<ModuleOptionsContext> {
|
||||||
self.edge_module_options_context.unwrap_or(context)
|
self.edge_module_options_context.unwrap_or(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn process_resolve_options_context(
|
fn process_resolve_options_context(
|
||||||
&self,
|
&self,
|
||||||
_context: ResolveOptionsContextVc,
|
_context: Vc<ResolveOptionsContext>,
|
||||||
) -> ResolveOptionsContextVc {
|
) -> Vc<ResolveOptionsContext> {
|
||||||
self.edge_resolve_options_context
|
self.edge_resolve_options_context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn process_module(
|
async fn process_module(
|
||||||
&self,
|
&self,
|
||||||
asset: ModuleVc,
|
asset: Vc<Box<dyn Module>>,
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
) -> Result<ModuleVc> {
|
) -> Result<Vc<Box<dyn Module>>> {
|
||||||
let new_asset = route_bootstrap(
|
let new_asset = route_bootstrap(
|
||||||
asset.into(),
|
Vc::upcast(asset),
|
||||||
context.into(),
|
Vc::upcast(context),
|
||||||
self.base_path,
|
self.base_path,
|
||||||
self.bootstrap_asset,
|
self.bootstrap_asset,
|
||||||
BootstrapConfigVc::cell(indexmap! {
|
Vc::cell(indexmap! {
|
||||||
"NAME".to_string() => self.entry_name.clone(),
|
"NAME".to_string() => self.entry_name.clone(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let asset = ChunkGroupFilesAsset {
|
let asset = ChunkGroupFilesAsset {
|
||||||
module: new_asset.into(),
|
module: Vc::upcast(new_asset),
|
||||||
client_root: self.output_path,
|
client_root: self.output_path,
|
||||||
chunking_context: self.edge_chunking_context,
|
chunking_context: self.edge_chunking_context,
|
||||||
runtime_entries: None,
|
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 once_cell::sync::Lazy;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use turbopack_binding::turbo::tasks::{
|
use turbo_tasks::Vc;
|
||||||
primitives::{StringVc, StringsVc},
|
use turbopack_binding::turbo::tasks::trace::TraceRawVcs;
|
||||||
trace::TraceRawVcs,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) struct DefaultFallbackFont {
|
pub(crate) struct DefaultFallbackFont {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
@ -34,9 +31,9 @@ pub(crate) static DEFAULT_SERIF_FONT: Lazy<DefaultFallbackFont> =
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub(crate) struct AutomaticFontFallback {
|
pub(crate) struct AutomaticFontFallback {
|
||||||
/// e.g. `__Roboto_Fallback_c123b8`
|
/// 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("{}")`
|
/// The name of font locally, used in `src: local("{}")`
|
||||||
pub local_font_family: StringVc,
|
pub local_font_family: Vc<String>,
|
||||||
pub adjustment: Option<FontAdjustment>,
|
pub adjustment: Option<FontAdjustment>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,17 +42,17 @@ pub(crate) struct AutomaticFontFallback {
|
||||||
pub(crate) enum FontFallback {
|
pub(crate) enum FontFallback {
|
||||||
/// An automatically generated fallback font generated by next/font. May
|
/// An automatically generated fallback font generated by next/font. May
|
||||||
/// include an optional [[FontAdjustment]].
|
/// include an optional [[FontAdjustment]].
|
||||||
Automatic(AutomaticFontFallbackVc),
|
Automatic(Vc<AutomaticFontFallback>),
|
||||||
/// There was an issue preparing the font fallback. Since resolving the
|
/// There was an issue preparing the font fallback. Since resolving the
|
||||||
/// font css cannot fail, proper Errors cannot be returned. Emit an issue,
|
/// font css cannot fail, proper Errors cannot be returned. Emit an issue,
|
||||||
/// return this and omit fallback information instead.
|
/// return this and omit fallback information instead.
|
||||||
Error,
|
Error,
|
||||||
/// A list of manually provided font names to use a fallback, as-is.
|
/// A list of manually provided font names to use a fallback, as-is.
|
||||||
Manual(StringsVc),
|
Manual(Vc<Vec<String>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(transparent)]
|
#[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
|
/// 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
|
/// 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 once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{trace::TraceRawVcs, Vc};
|
||||||
primitives::{StringVc, StringsVc, U32Vc},
|
use turbopack_binding::{
|
||||||
trace::TraceRawVcs,
|
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::{
|
use crate::{
|
||||||
next_font::{
|
next_font::{
|
||||||
font_fallback::{
|
font_fallback::{
|
||||||
AutomaticFontFallback, FontAdjustment, FontFallback, FontFallbackVc,
|
AutomaticFontFallback, FontAdjustment, FontFallback, DEFAULT_SANS_SERIF_FONT,
|
||||||
DEFAULT_SANS_SERIF_FONT, DEFAULT_SERIF_FONT,
|
DEFAULT_SERIF_FONT,
|
||||||
},
|
},
|
||||||
issue::NextFontIssue,
|
issue::NextFontIssue,
|
||||||
util::{get_scoped_font_family, FontFamilyType},
|
util::{get_scoped_font_family, FontFamilyType},
|
||||||
|
@ -46,13 +46,13 @@ struct Fallback {
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) async fn get_font_fallback(
|
pub(super) async fn get_font_fallback(
|
||||||
context: FileSystemPathVc,
|
context: Vc<FileSystemPath>,
|
||||||
options_vc: NextFontGoogleOptionsVc,
|
options_vc: Vc<NextFontGoogleOptions>,
|
||||||
request_hash: U32Vc,
|
request_hash: Vc<u32>,
|
||||||
) -> Result<FontFallbackVc> {
|
) -> Result<Vc<FontFallback>> {
|
||||||
let options = options_vc.await?;
|
let options = options_vc.await?;
|
||||||
Ok(match &options.fallback {
|
Ok(match &options.fallback {
|
||||||
Some(fallback) => FontFallback::Manual(StringsVc::cell(fallback.clone())).cell(),
|
Some(fallback) => FontFallback::Manual(Vc::cell(fallback.clone())).cell(),
|
||||||
None => {
|
None => {
|
||||||
let metrics_json =
|
let metrics_json =
|
||||||
load_next_json(context, "/dist/server/capsize-font-metrics.json").await?;
|
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(),
|
options_vc.font_family(),
|
||||||
request_hash,
|
request_hash,
|
||||||
),
|
),
|
||||||
local_font_family: StringVc::cell(fallback.font_family),
|
local_font_family: Vc::cell(fallback.font_family),
|
||||||
adjustment: fallback.adjustment,
|
adjustment: fallback.adjustment,
|
||||||
}
|
}
|
||||||
.cell(),
|
.cell(),
|
||||||
|
@ -79,17 +79,14 @@ pub(super) async fn get_font_fallback(
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
NextFontIssue {
|
NextFontIssue {
|
||||||
path: context,
|
path: context,
|
||||||
title: StringVc::cell(format!(
|
title: Vc::cell(format!(
|
||||||
"Failed to find font override values for font `{}`",
|
"Failed to find font override values for font `{}`",
|
||||||
&options.font_family,
|
&options.font_family,
|
||||||
)),
|
)),
|
||||||
description: StringVc::cell(
|
description: Vc::cell("Skipping generating a fallback font.".to_owned()),
|
||||||
"Skipping generating a fallback font.".to_owned(),
|
|
||||||
),
|
|
||||||
severity: IssueSeverity::Warning.cell(),
|
severity: IssueSeverity::Warning.cell(),
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
.as_issue()
|
|
||||||
.emit();
|
.emit();
|
||||||
FontFallback::Error.cell()
|
FontFallback::Error.cell()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,57 +4,48 @@ use anyhow::{bail, Context, Result};
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{
|
turbo::{
|
||||||
tasks::{
|
tasks::{Completion, Value},
|
||||||
primitives::{OptionStringVc, StringVc, U32Vc},
|
|
||||||
CompletionVc, Value,
|
|
||||||
},
|
|
||||||
tasks_bytes::stream::SingleValue,
|
tasks_bytes::stream::SingleValue,
|
||||||
tasks_env::{CommandLineProcessEnvVc, ProcessEnv},
|
tasks_env::{CommandLineProcessEnv, ProcessEnv},
|
||||||
tasks_fetch::fetch,
|
tasks_fetch::fetch,
|
||||||
tasks_fs::{
|
tasks_fs::{
|
||||||
json::parse_json_with_source_context, DiskFileSystemVc, File, FileContent, FileSystem,
|
json::parse_json_with_source_context, DiskFileSystem, File, FileContent, FileSystem,
|
||||||
FileSystemPathVc,
|
FileSystemPath,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
|
asset::AssetContent,
|
||||||
context::AssetContext,
|
context::AssetContext,
|
||||||
ident::AssetIdentVc,
|
ident::AssetIdent,
|
||||||
issue::IssueSeverity,
|
issue::{IssueExt, IssueSeverity},
|
||||||
reference_type::{InnerAssetsVc, ReferenceType},
|
reference_type::{InnerAssets, ReferenceType},
|
||||||
resolve::{
|
resolve::{
|
||||||
options::{
|
options::{ImportMapResult, ImportMapping, ImportMappingReplacement},
|
||||||
ImportMapResult, ImportMapResultVc, ImportMapping, ImportMappingReplacement,
|
parse::Request,
|
||||||
ImportMappingReplacementVc, ImportMappingVc,
|
pattern::QueryMap,
|
||||||
},
|
|
||||||
parse::{Request, RequestVc},
|
|
||||||
pattern::QueryMapVc,
|
|
||||||
ResolveResult,
|
ResolveResult,
|
||||||
},
|
},
|
||||||
virtual_source::VirtualSourceVc,
|
virtual_source::VirtualSource,
|
||||||
},
|
|
||||||
node::{
|
|
||||||
debug::should_debug,
|
|
||||||
evaluate::evaluate,
|
|
||||||
execution_context::{ExecutionContext, ExecutionContextVc},
|
|
||||||
},
|
},
|
||||||
|
node::{debug::should_debug, evaluate::evaluate, execution_context::ExecutionContext},
|
||||||
turbopack::evaluate_context::node_evaluate_asset_context,
|
turbopack::evaluate_context::node_evaluate_asset_context,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
font_fallback::get_font_fallback,
|
font_fallback::get_font_fallback,
|
||||||
options::{options_from_request, FontDataEntry, FontWeights, NextFontGoogleOptionsVc},
|
options::{options_from_request, FontDataEntry, FontWeights, NextFontGoogleOptions},
|
||||||
stylesheet::build_stylesheet,
|
stylesheet::build_stylesheet,
|
||||||
util::{get_font_axes, get_stylesheet_url},
|
util::{get_font_axes, get_stylesheet_url},
|
||||||
};
|
};
|
||||||
use super::{
|
use super::{
|
||||||
font_fallback::{FontFallback, FontFallbackVc},
|
font_fallback::FontFallback,
|
||||||
util::{
|
util::{
|
||||||
get_request_hash, get_request_id, get_scoped_font_family, FontCssProperties,
|
get_request_hash, get_request_id, get_scoped_font_family, FontCssProperties, FontFamilyType,
|
||||||
FontCssPropertiesVc, FontFamilyType,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crate::{embed_js::next_js_file_path, util::load_next_json};
|
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)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub(crate) struct NextFontGoogleReplacer {
|
pub(crate) struct NextFontGoogleReplacer {
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextFontGoogleReplacerVc {
|
impl NextFontGoogleReplacer {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(project_path: FileSystemPathVc) -> Self {
|
pub fn new(project_path: Vc<FileSystemPath>) -> Vc<Self> {
|
||||||
Self::cell(NextFontGoogleReplacer { project_path })
|
Self::cell(NextFontGoogleReplacer { project_path })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +83,7 @@ impl NextFontGoogleReplacerVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ImportMappingReplacement for NextFontGoogleReplacer {
|
impl ImportMappingReplacement for NextFontGoogleReplacer {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn replace(&self, _capture: &str) -> ImportMappingVc {
|
fn replace(&self, _capture: String) -> Vc<ImportMapping> {
|
||||||
ImportMapping::Ignore.into()
|
ImportMapping::Ignore.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,9 +93,9 @@ impl ImportMappingReplacement for NextFontGoogleReplacer {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn result(
|
async fn result(
|
||||||
&self,
|
&self,
|
||||||
_context: FileSystemPathVc,
|
_context: Vc<FileSystemPath>,
|
||||||
request: RequestVc,
|
request: Vc<Request>,
|
||||||
) -> Result<ImportMapResultVc> {
|
) -> Result<Vc<ImportMapResult>> {
|
||||||
let request = &*request.await?;
|
let request = &*request.await?;
|
||||||
let Request::Module {
|
let Request::Module {
|
||||||
module: _,
|
module: _,
|
||||||
|
@ -121,62 +112,65 @@ impl ImportMappingReplacement for NextFontGoogleReplacer {
|
||||||
let request_hash = get_request_hash(*query_vc);
|
let request_hash = get_request_hash(*query_vc);
|
||||||
let fallback = get_font_fallback(self.project_path, options, request_hash);
|
let fallback = get_font_fallback(self.project_path, options, request_hash);
|
||||||
let properties = get_font_css_properties(options, fallback, request_hash).await?;
|
let properties = get_font_css_properties(options, fallback, request_hash).await?;
|
||||||
let js_asset = VirtualSourceVc::new(
|
let js_asset = VirtualSource::new(
|
||||||
next_js_file_path("internal/font/google")
|
next_js_file_path("internal/font/google".to_string())
|
||||||
.join(&format!("{}.js", get_request_id(options.font_family(), request_hash).await?)),
|
.join(format!("{}.js", get_request_id(options.font_family(), request_hash).await?)),
|
||||||
FileContent::Content(
|
AssetContent::file(FileContent::Content(
|
||||||
formatdoc!(
|
formatdoc!(
|
||||||
r#"
|
r#"
|
||||||
import cssModule from "@vercel/turbopack-next/internal/font/google/cssmodule.module.css?{}";
|
import cssModule from "@vercel/turbopack-next/internal/font/google/cssmodule.module.css?{}";
|
||||||
const fontData = {{
|
const fontData = {{
|
||||||
className: cssModule.className,
|
className: cssModule.className,
|
||||||
style: {{
|
style: {{
|
||||||
fontFamily: "{}",
|
fontFamily: "{}",
|
||||||
{}{}
|
{}{}
|
||||||
}},
|
}},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
if (cssModule.variable != null) {{
|
if (cssModule.variable != null) {{
|
||||||
fontData.variable = cssModule.variable;
|
fontData.variable = cssModule.variable;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
export default fontData;
|
export default fontData;
|
||||||
"#,
|
"#,
|
||||||
// Pass along whichever options we received to the css handler
|
// Pass along whichever options we received to the css handler
|
||||||
qstring::QString::new(query.as_ref().unwrap().iter().collect()),
|
qstring::QString::new(query.as_ref().unwrap().iter().collect()),
|
||||||
properties.font_family.await?,
|
properties.font_family.await?,
|
||||||
properties
|
properties
|
||||||
.weight
|
.weight
|
||||||
.await?
|
.await?
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|w| format!("fontWeight: {},\n", w))
|
.map(|w| format!("fontWeight: {},\n", w))
|
||||||
.unwrap_or_else(|| "".to_owned()),
|
.unwrap_or_else(|| "".to_owned()),
|
||||||
properties
|
properties
|
||||||
.style
|
.style
|
||||||
.await?
|
.await?
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| format!("fontStyle: \"{}\",\n", s))
|
.map(|s| format!("fontStyle: \"{}\",\n", s))
|
||||||
.unwrap_or_else(|| "".to_owned()),
|
.unwrap_or_else(|| "".to_owned()),
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
)
|
)
|
||||||
.into(),
|
.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)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextFontGoogleCssModuleReplacer {
|
pub struct NextFontGoogleCssModuleReplacer {
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextFontGoogleCssModuleReplacerVc {
|
impl NextFontGoogleCssModuleReplacer {
|
||||||
#[turbo_tasks::function]
|
#[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 {
|
Self::cell(NextFontGoogleCssModuleReplacer {
|
||||||
project_path,
|
project_path,
|
||||||
execution_context,
|
execution_context,
|
||||||
|
@ -187,7 +181,7 @@ impl NextFontGoogleCssModuleReplacerVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
|
impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn replace(&self, _capture: &str) -> ImportMappingVc {
|
fn replace(&self, _capture: String) -> Vc<ImportMapping> {
|
||||||
ImportMapping::Ignore.into()
|
ImportMapping::Ignore.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,9 +192,9 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn result(
|
async fn result(
|
||||||
&self,
|
&self,
|
||||||
_context: FileSystemPathVc,
|
_context: Vc<FileSystemPath>,
|
||||||
request: RequestVc,
|
request: Vc<Request>,
|
||||||
) -> Result<ImportMapResultVc> {
|
) -> Result<Vc<ImportMapResult>> {
|
||||||
let request = &*request.await?;
|
let request = &*request.await?;
|
||||||
let Request::Module {
|
let Request::Module {
|
||||||
module: _,
|
module: _,
|
||||||
|
@ -220,7 +214,7 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
|
||||||
options.font_family(),
|
options.font_family(),
|
||||||
request_hash,
|
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",
|
"/{}.module.css",
|
||||||
get_request_id(options.font_family(), request_hash).await?
|
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
|
// When running Next.js integration tests, use the mock data available in
|
||||||
// process.env.NEXT_FONT_GOOGLE_MOCKED_RESPONSES instead of making real
|
// process.env.NEXT_FONT_GOOGLE_MOCKED_RESPONSES instead of making real
|
||||||
// requests to Google Fonts.
|
// requests to Google Fonts.
|
||||||
let env = CommandLineProcessEnvVc::new().as_process_env();
|
let env = Vc::upcast::<Box<dyn ProcessEnv>>(CommandLineProcessEnv::new());
|
||||||
let mocked_responses_path = &*env.read("NEXT_FONT_GOOGLE_MOCKED_RESPONSES").await?;
|
let mocked_responses_path = &*env
|
||||||
|
.read("NEXT_FONT_GOOGLE_MOCKED_RESPONSES".to_string())
|
||||||
|
.await?;
|
||||||
let stylesheet_str = mocked_responses_path
|
let stylesheet_str = mocked_responses_path
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|
@ -248,26 +244,28 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
|
||||||
};
|
};
|
||||||
|
|
||||||
let font_fallback = get_font_fallback(self.project_path, options, request_hash);
|
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,
|
css_virtual_path,
|
||||||
FileContent::Content(
|
AssetContent::file(
|
||||||
build_stylesheet(
|
FileContent::Content(
|
||||||
OptionStringVc::cell(stylesheet),
|
build_stylesheet(
|
||||||
get_font_css_properties(options, font_fallback, request_hash),
|
Vc::cell(stylesheet),
|
||||||
font_fallback,
|
get_font_css_properties(options, font_fallback, request_hash),
|
||||||
|
font_fallback,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.into(),
|
||||||
)
|
)
|
||||||
.await?
|
|
||||||
.into(),
|
.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]
|
#[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(
|
let data: FontData = load_next_json(
|
||||||
project_root,
|
project_root,
|
||||||
"/dist/compiled/@next/font/dist/google/font-data.json",
|
"/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.
|
/// font family names.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn update_google_stylesheet(
|
async fn update_google_stylesheet(
|
||||||
stylesheet: StringVc,
|
stylesheet: Vc<String>,
|
||||||
options: NextFontGoogleOptionsVc,
|
options: Vc<NextFontGoogleOptions>,
|
||||||
scoped_font_family: StringVc,
|
scoped_font_family: Vc<String>,
|
||||||
) -> Result<StringVc> {
|
) -> Result<Vc<String>> {
|
||||||
// Update font-family definitions to the scoped name
|
// Update font-family definitions to the scoped name
|
||||||
// TODO: Do this more resiliently, e.g. transforming an swc ast
|
// 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: '{}';", &*options.await?.font_family),
|
||||||
&format!("font-family: '{}';", &*scoped_font_family.await?),
|
&format!("font-family: '{}';", &*scoped_font_family.await?),
|
||||||
)))
|
)))
|
||||||
|
@ -295,23 +293,26 @@ async fn update_google_stylesheet(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn get_stylesheet_url_from_options(
|
async fn get_stylesheet_url_from_options(
|
||||||
options: NextFontGoogleOptionsVc,
|
options: Vc<NextFontGoogleOptions>,
|
||||||
font_data: FontDataVc,
|
font_data: Vc<FontData>,
|
||||||
) -> Result<StringVc> {
|
) -> Result<Vc<String>> {
|
||||||
#[allow(unused_mut, unused_assignments)] // This is used in test environments
|
#[allow(unused_mut, unused_assignments)] // This is used in test environments
|
||||||
let mut css_url: Option<String> = None;
|
let mut css_url: Option<String> = None;
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
use turbopack_binding::turbo::tasks_env::{CommandLineProcessEnvVc, ProcessEnv};
|
use turbopack_binding::turbo::tasks_env::{CommandLineProcessEnv, ProcessEnv};
|
||||||
|
|
||||||
let env = CommandLineProcessEnvVc::new();
|
let env = CommandLineProcessEnv::new();
|
||||||
if let Some(url) = &*env.read("TURBOPACK_TEST_ONLY_MOCK_SERVER").await? {
|
if let Some(url) = &*env
|
||||||
|
.read("TURBOPACK_TEST_ONLY_MOCK_SERVER".to_string())
|
||||||
|
.await?
|
||||||
|
{
|
||||||
css_url = Some(format!("{}/css2", url));
|
css_url = Some(format!("{}/css2", url));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let options = options.await?;
|
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),
|
css_url.as_deref().unwrap_or(GOOGLE_FONTS_STYLESHEET_URL),
|
||||||
&options.font_family,
|
&options.font_family,
|
||||||
&get_font_axes(
|
&get_font_axes(
|
||||||
|
@ -327,10 +328,10 @@ async fn get_stylesheet_url_from_options(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn get_font_css_properties(
|
async fn get_font_css_properties(
|
||||||
options_vc: NextFontGoogleOptionsVc,
|
options_vc: Vc<NextFontGoogleOptions>,
|
||||||
font_fallback: FontFallbackVc,
|
font_fallback: Vc<FontFallback>,
|
||||||
request_hash: U32Vc,
|
request_hash: Vc<u32>,
|
||||||
) -> Result<FontCssPropertiesVc> {
|
) -> Result<Vc<FontCssProperties>> {
|
||||||
let options = &*options_vc.await?;
|
let options = &*options_vc.await?;
|
||||||
let scoped_font_family = &*get_scoped_font_family(
|
let scoped_font_family = &*get_scoped_font_family(
|
||||||
FontFamilyType::WebFont.cell(),
|
FontFamilyType::WebFont.cell(),
|
||||||
|
@ -352,22 +353,22 @@ async fn get_font_css_properties(
|
||||||
FontFallback::Error => {}
|
FontFallback::Error => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(FontCssPropertiesVc::cell(FontCssProperties {
|
Ok(FontCssProperties::cell(FontCssProperties {
|
||||||
font_family: StringVc::cell(font_families.join(", ")),
|
font_family: Vc::cell(font_families.join(", ")),
|
||||||
weight: OptionStringVc::cell(match &options.weights {
|
weight: Vc::cell(match &options.weights {
|
||||||
FontWeights::Variable => None,
|
FontWeights::Variable => None,
|
||||||
FontWeights::Fixed(weights) => weights.first().map(|w| w.to_string()),
|
FontWeights::Fixed(weights) => weights.first().map(|w| w.to_string()),
|
||||||
}),
|
}),
|
||||||
style: OptionStringVc::cell(options.styles.first().cloned()),
|
style: Vc::cell(options.styles.first().cloned()),
|
||||||
variable: OptionStringVc::cell(options.variable.clone()),
|
variable: Vc::cell(options.variable.clone()),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn font_options_from_query_map(
|
async fn font_options_from_query_map(
|
||||||
query: QueryMapVc,
|
query: Vc<QueryMap>,
|
||||||
font_data: FontDataVc,
|
font_data: Vc<FontData>,
|
||||||
) -> Result<NextFontGoogleOptionsVc> {
|
) -> Result<Vc<NextFontGoogleOptions>> {
|
||||||
let query_map = &*query.await?;
|
let query_map = &*query.await?;
|
||||||
// These are invariants from the next/font swc transform. Regular errors instead
|
// These are invariants from the next/font swc transform. Regular errors instead
|
||||||
// of Issues should be okay.
|
// 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?)
|
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(
|
async fn fetch_real_stylesheet(
|
||||||
stylesheet_url: StringVc,
|
stylesheet_url: Vc<String>,
|
||||||
css_virtual_path: FileSystemPathVc,
|
css_virtual_path: Vc<FileSystemPath>,
|
||||||
) -> Result<Option<StringVc>> {
|
) -> Result<Option<Vc<String>>> {
|
||||||
let stylesheet = fetch(
|
let stylesheet = fetch(
|
||||||
stylesheet_url,
|
stylesheet_url,
|
||||||
OptionStringVc::cell(Some(USER_AGENT_FOR_GOOGLE_FONTS.to_owned())),
|
Vc::cell(Some(USER_AGENT_FOR_GOOGLE_FONTS.to_owned())),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -408,7 +409,6 @@ async fn fetch_real_stylesheet(
|
||||||
// TODO(WEB-283): Use fallback in dev in this case
|
// TODO(WEB-283): Use fallback in dev in this case
|
||||||
// TODO(WEB-293): Fail production builds (not dev) in this case
|
// TODO(WEB-293): Fail production builds (not dev) in this case
|
||||||
err.to_issue(IssueSeverity::Warning.into(), css_virtual_path)
|
err.to_issue(IssueSeverity::Warning.into(), css_virtual_path)
|
||||||
.as_issue()
|
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -417,12 +417,12 @@ async fn fetch_real_stylesheet(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_mock_stylesheet(
|
async fn get_mock_stylesheet(
|
||||||
stylesheet_url: StringVc,
|
stylesheet_url: Vc<String>,
|
||||||
mocked_responses_path: &str,
|
mocked_responses_path: &str,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
) -> Result<Option<StringVc>> {
|
) -> Result<Option<Vc<String>>> {
|
||||||
let response_path = Path::new(&mocked_responses_path);
|
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(),
|
"mock".to_string(),
|
||||||
response_path
|
response_path
|
||||||
.parent()
|
.parent()
|
||||||
|
@ -430,8 +430,7 @@ async fn get_mock_stylesheet(
|
||||||
.to_str()
|
.to_str()
|
||||||
.context("Must exist")?
|
.context("Must exist")?
|
||||||
.to_string(),
|
.to_string(),
|
||||||
)
|
));
|
||||||
.as_file_system();
|
|
||||||
|
|
||||||
let ExecutionContext {
|
let ExecutionContext {
|
||||||
env,
|
env,
|
||||||
|
@ -439,34 +438,35 @@ async fn get_mock_stylesheet(
|
||||||
chunking_context,
|
chunking_context,
|
||||||
} = *execution_context.await?;
|
} = *execution_context.await?;
|
||||||
let context = node_evaluate_asset_context(execution_context, None, None);
|
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(
|
let mocked_response_asset = context.process(
|
||||||
VirtualSourceVc::new(
|
Vc::upcast(VirtualSource::new(
|
||||||
loader_path,
|
loader_path,
|
||||||
File::from(format!(
|
AssetContent::file(
|
||||||
"import data from './{}'; export default function load() {{ return data; }};",
|
File::from(format!(
|
||||||
response_path
|
"import data from './{}'; export default function load() {{ return data; }};",
|
||||||
.file_name()
|
response_path
|
||||||
.context("Must exist")?
|
.file_name()
|
||||||
.to_string_lossy(),
|
.context("Must exist")?
|
||||||
))
|
.to_string_lossy(),
|
||||||
.into(),
|
))
|
||||||
)
|
.into(),
|
||||||
.into(),
|
),
|
||||||
Value::new(ReferenceType::Internal(InnerAssetsVc::empty())),
|
)),
|
||||||
|
Value::new(ReferenceType::Internal(InnerAssets::empty())),
|
||||||
);
|
);
|
||||||
|
|
||||||
let root = mock_fs.root();
|
let root = mock_fs.root();
|
||||||
let val = evaluate(
|
let val = evaluate(
|
||||||
mocked_response_asset.into(),
|
Vc::upcast(mocked_response_asset),
|
||||||
root,
|
root,
|
||||||
env,
|
env,
|
||||||
AssetIdentVc::from_path(loader_path),
|
AssetIdent::from_path(loader_path),
|
||||||
context,
|
context,
|
||||||
chunking_context,
|
chunking_context,
|
||||||
None,
|
None,
|
||||||
vec![],
|
vec![],
|
||||||
CompletionVc::immutable(),
|
Completion::immutable(),
|
||||||
should_debug("next_font::google"),
|
should_debug("next_font::google"),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -479,7 +479,7 @@ async fn get_mock_stylesheet(
|
||||||
.get(&*stylesheet_url.await?)
|
.get(&*stylesheet_url.await?)
|
||||||
.context("url not found")?
|
.context("url not found")?
|
||||||
.clone()
|
.clone()
|
||||||
.map(StringVc::cell))
|
.map(Vc::cell))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("Unexpected error evaluating JS")
|
panic!("Unexpected error evaluating JS")
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use indexmap::{indexset, IndexMap, IndexSet};
|
use indexmap::{indexset, IndexMap, IndexSet};
|
||||||
use serde::{Deserialize, Serialize};
|
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};
|
use super::request::{NextFontRequest, OneOrManyStrings};
|
||||||
|
|
||||||
|
@ -28,15 +29,15 @@ pub(super) struct NextFontGoogleOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextFontGoogleOptionsVc {
|
impl NextFontGoogleOptions {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(options: Value<NextFontGoogleOptions>) -> NextFontGoogleOptionsVc {
|
pub fn new(options: Value<NextFontGoogleOptions>) -> Vc<NextFontGoogleOptions> {
|
||||||
Self::cell(options.into_value())
|
Self::cell(options.into_value())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn font_family(self) -> Result<StringVc> {
|
pub async fn font_family(self: Vc<Self>) -> Result<Vc<String>> {
|
||||||
Ok(StringVc::cell((*self.await?.font_family).to_owned()))
|
Ok(Vc::cell((*self.await?.font_family).to_owned()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
use anyhow::Result;
|
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::{
|
use crate::next_font::{
|
||||||
font_fallback::{FontFallbackVc, FontFallbacksVc},
|
font_fallback::FontFallback,
|
||||||
stylesheet::{build_fallback_definition, build_font_class_rules},
|
stylesheet::{build_fallback_definition, build_font_class_rules},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) async fn build_stylesheet(
|
pub(super) async fn build_stylesheet(
|
||||||
base_stylesheet: OptionStringVc,
|
base_stylesheet: Vc<Option<String>>,
|
||||||
font_css_properties: FontCssPropertiesVc,
|
font_css_properties: Vc<FontCssProperties>,
|
||||||
font_fallback: FontFallbackVc,
|
font_fallback: Vc<FontFallback>,
|
||||||
) -> Result<StringVc> {
|
) -> Result<Vc<String>> {
|
||||||
let base_stylesheet = &*base_stylesheet.await?;
|
let base_stylesheet = &*base_stylesheet.await?;
|
||||||
let mut stylesheet = base_stylesheet
|
let mut stylesheet = base_stylesheet
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or_else(|| "".to_owned(), |s| s.to_owned());
|
.map_or_else(|| "".to_owned(), |s| s.to_owned());
|
||||||
|
|
||||||
stylesheet
|
stylesheet.push_str(&build_fallback_definition(Vc::cell(vec![font_fallback])).await?);
|
||||||
.push_str(&build_fallback_definition(FontFallbacksVc::cell(vec![font_fallback])).await?);
|
|
||||||
stylesheet.push_str(&build_font_class_rules(font_css_properties).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::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::FileSystemPathVc,
|
turbo::tasks_fs::FileSystemPath,
|
||||||
turbopack::core::issue::{Issue, IssueSeverityVc, IssueVc},
|
turbopack::core::issue::{Issue, IssueSeverity},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub(crate) struct NextFontIssue {
|
pub(crate) struct NextFontIssue {
|
||||||
pub(crate) path: FileSystemPathVc,
|
pub(crate) path: Vc<FileSystemPath>,
|
||||||
pub(crate) title: StringVc,
|
pub(crate) title: Vc<String>,
|
||||||
pub(crate) description: StringVc,
|
pub(crate) description: Vc<String>,
|
||||||
pub(crate) severity: IssueSeverityVc,
|
pub(crate) severity: Vc<IssueSeverity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Issue for NextFontIssue {
|
impl Issue for NextFontIssue {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn category(&self) -> StringVc {
|
fn category(&self) -> Vc<String> {
|
||||||
StringVc::cell("other".to_string())
|
Vc::cell("other".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn severity(&self) -> IssueSeverityVc {
|
fn severity(&self) -> Vc<IssueSeverity> {
|
||||||
self.severity
|
self.severity
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn context(&self) -> FileSystemPathVc {
|
fn context(&self) -> Vc<FileSystemPath> {
|
||||||
self.path
|
self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn title(&self) -> StringVc {
|
fn title(&self) -> Vc<String> {
|
||||||
self.title
|
self.title
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn description(&self) -> StringVc {
|
fn description(&self) -> Vc<String> {
|
||||||
self.description
|
self.description
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,16 @@ use allsorts::{
|
||||||
Font,
|
Font,
|
||||||
};
|
};
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use turbopack_binding::turbo::{
|
use turbo_tasks::Vc;
|
||||||
tasks::primitives::{StringVc, StringsVc, U32Vc},
|
use turbopack_binding::turbo::tasks_fs::{FileContent, FileSystemPath};
|
||||||
tasks_fs::{FileContent, FileSystemPathVc},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
options::{FontDescriptor, FontDescriptors, FontWeight, NextFontLocalOptionsVc},
|
options::{FontDescriptor, FontDescriptors, FontWeight, NextFontLocalOptions},
|
||||||
request::AdjustFontFallback,
|
request::AdjustFontFallback,
|
||||||
};
|
};
|
||||||
use crate::next_font::{
|
use crate::next_font::{
|
||||||
font_fallback::{
|
font_fallback::{
|
||||||
AutomaticFontFallback, DefaultFallbackFont, FontAdjustment, FontFallback, FontFallbacksVc,
|
AutomaticFontFallback, DefaultFallbackFont, FontAdjustment, FontFallback, FontFallbacks,
|
||||||
DEFAULT_SANS_SERIF_FONT, DEFAULT_SERIF_FONT,
|
DEFAULT_SANS_SERIF_FONT, DEFAULT_SERIF_FONT,
|
||||||
},
|
},
|
||||||
util::{get_scoped_font_family, FontFamilyType},
|
util::{get_scoped_font_family, FontFamilyType},
|
||||||
|
@ -28,10 +26,10 @@ static BOLD_WEIGHT: f64 = 700.0;
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) async fn get_font_fallbacks(
|
pub(super) async fn get_font_fallbacks(
|
||||||
context: FileSystemPathVc,
|
context: Vc<FileSystemPath>,
|
||||||
options_vc: NextFontLocalOptionsVc,
|
options_vc: Vc<NextFontLocalOptions>,
|
||||||
request_hash: U32Vc,
|
request_hash: Vc<u32>,
|
||||||
) -> Result<FontFallbacksVc> {
|
) -> Result<Vc<FontFallbacks>> {
|
||||||
let options = &*options_vc.await?;
|
let options = &*options_vc.await?;
|
||||||
let mut font_fallbacks = vec![];
|
let mut font_fallbacks = vec![];
|
||||||
let scoped_font_family = get_scoped_font_family(
|
let scoped_font_family = get_scoped_font_family(
|
||||||
|
@ -45,7 +43,7 @@ pub(super) async fn get_font_fallbacks(
|
||||||
FontFallback::Automatic(
|
FontFallback::Automatic(
|
||||||
AutomaticFontFallback {
|
AutomaticFontFallback {
|
||||||
scoped_font_family,
|
scoped_font_family,
|
||||||
local_font_family: StringVc::cell("Arial".to_owned()),
|
local_font_family: Vc::cell("Arial".to_owned()),
|
||||||
adjustment: Some(
|
adjustment: Some(
|
||||||
get_font_adjustment(context, options_vc, &DEFAULT_SANS_SERIF_FONT).await?,
|
get_font_adjustment(context, options_vc, &DEFAULT_SANS_SERIF_FONT).await?,
|
||||||
),
|
),
|
||||||
|
@ -58,7 +56,7 @@ pub(super) async fn get_font_fallbacks(
|
||||||
FontFallback::Automatic(
|
FontFallback::Automatic(
|
||||||
AutomaticFontFallback {
|
AutomaticFontFallback {
|
||||||
scoped_font_family,
|
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(
|
adjustment: Some(
|
||||||
get_font_adjustment(context, options_vc, &DEFAULT_SERIF_FONT).await?,
|
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 {
|
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(
|
async fn get_font_adjustment(
|
||||||
context: FileSystemPathVc,
|
context: Vc<FileSystemPath>,
|
||||||
options: NextFontLocalOptionsVc,
|
options: Vc<NextFontLocalOptions>,
|
||||||
fallback_font: &DefaultFallbackFont,
|
fallback_font: &DefaultFallbackFont,
|
||||||
) -> Result<FontAdjustment> {
|
) -> Result<FontAdjustment> {
|
||||||
let options = &*options.await?;
|
let options = &*options.await?;
|
||||||
let main_descriptor = pick_font_for_fallback_generation(&options.fonts)?;
|
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 {
|
let font_file_rope = match font_file {
|
||||||
FileContent::NotFound => bail!("Expected font file content"),
|
FileContent::NotFound => bail!("Expected font file content"),
|
||||||
FileContent::Content(file) => file.content(),
|
FileContent::Content(file) => file.content(),
|
||||||
|
|
|
@ -1,37 +1,30 @@
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{
|
turbo::{
|
||||||
tasks::{
|
tasks::Value,
|
||||||
primitives::{OptionStringVc, U32Vc},
|
tasks_fs::{json::parse_json_with_source_context, FileContent, FileSystemPath},
|
||||||
Value,
|
|
||||||
},
|
|
||||||
tasks_fs::{json::parse_json_with_source_context, FileContent, FileSystemPathVc},
|
|
||||||
},
|
},
|
||||||
turbopack::core::{
|
turbopack::core::{
|
||||||
|
asset::AssetContent,
|
||||||
resolve::{
|
resolve::{
|
||||||
options::{
|
options::{ImportMapResult, ImportMapping, ImportMappingReplacement},
|
||||||
ImportMapResult, ImportMapResultVc, ImportMapping, ImportMappingReplacement,
|
parse::Request,
|
||||||
ImportMappingReplacementVc, ImportMappingVc,
|
pattern::QueryMap,
|
||||||
},
|
|
||||||
parse::{Request, RequestVc},
|
|
||||||
pattern::QueryMapVc,
|
|
||||||
ResolveResult,
|
ResolveResult,
|
||||||
},
|
},
|
||||||
virtual_source::VirtualSourceVc,
|
virtual_source::VirtualSource,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
font_fallback::get_font_fallbacks,
|
font_fallback::get_font_fallbacks,
|
||||||
options::{options_from_request, FontDescriptors, NextFontLocalOptionsVc},
|
options::{options_from_request, FontDescriptors, NextFontLocalOptions},
|
||||||
stylesheet::build_stylesheet,
|
stylesheet::build_stylesheet,
|
||||||
util::build_font_family_string,
|
util::build_font_family_string,
|
||||||
};
|
};
|
||||||
use super::{
|
use super::{font_fallback::FontFallbacks, util::FontCssProperties};
|
||||||
font_fallback::FontFallbacksVc,
|
|
||||||
util::{FontCssProperties, FontCssPropertiesVc},
|
|
||||||
};
|
|
||||||
use crate::next_font::{
|
use crate::next_font::{
|
||||||
local::options::FontWeight,
|
local::options::FontWeight,
|
||||||
util::{get_request_hash, get_request_id},
|
util::{get_request_hash, get_request_id},
|
||||||
|
@ -45,13 +38,13 @@ pub mod util;
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub(crate) struct NextFontLocalReplacer {
|
pub(crate) struct NextFontLocalReplacer {
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextFontLocalReplacerVc {
|
impl NextFontLocalReplacer {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(project_path: FileSystemPathVc) -> Self {
|
pub fn new(project_path: Vc<FileSystemPath>) -> Vc<Self> {
|
||||||
Self::cell(NextFontLocalReplacer { project_path })
|
Self::cell(NextFontLocalReplacer { project_path })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +52,7 @@ impl NextFontLocalReplacerVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ImportMappingReplacement for NextFontLocalReplacer {
|
impl ImportMappingReplacement for NextFontLocalReplacer {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn replace(&self, _capture: &str) -> ImportMappingVc {
|
fn replace(&self, _capture: String) -> Vc<ImportMapping> {
|
||||||
ImportMapping::Ignore.into()
|
ImportMapping::Ignore.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,9 +62,9 @@ impl ImportMappingReplacement for NextFontLocalReplacer {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn result(
|
async fn result(
|
||||||
&self,
|
&self,
|
||||||
context: FileSystemPathVc,
|
context: Vc<FileSystemPath>,
|
||||||
request: RequestVc,
|
request: Vc<Request>,
|
||||||
) -> Result<ImportMapResultVc> {
|
) -> Result<Vc<ImportMapResult>> {
|
||||||
let Request::Module {
|
let Request::Module {
|
||||||
module: _,
|
module: _,
|
||||||
path: _,
|
path: _,
|
||||||
|
@ -119,27 +112,27 @@ impl ImportMappingReplacement for NextFontLocalReplacer {
|
||||||
.map(|s| format!("fontStyle: \"{}\",\n", s))
|
.map(|s| format!("fontStyle: \"{}\",\n", s))
|
||||||
.unwrap_or_else(|| "".to_owned()),
|
.unwrap_or_else(|| "".to_owned()),
|
||||||
);
|
);
|
||||||
let js_asset = VirtualSourceVc::new(
|
let js_asset = VirtualSource::new(
|
||||||
context.join(&format!(
|
context.join(format!(
|
||||||
"{}.js",
|
"{}.js",
|
||||||
get_request_id(options_vc.font_family(), request_hash).await?
|
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)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextFontLocalCssModuleReplacer {
|
pub struct NextFontLocalCssModuleReplacer {
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextFontLocalCssModuleReplacerVc {
|
impl NextFontLocalCssModuleReplacer {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(project_path: FileSystemPathVc) -> Self {
|
pub fn new(project_path: Vc<FileSystemPath>) -> Vc<Self> {
|
||||||
Self::cell(NextFontLocalCssModuleReplacer { project_path })
|
Self::cell(NextFontLocalCssModuleReplacer { project_path })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,7 +140,7 @@ impl NextFontLocalCssModuleReplacerVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ImportMappingReplacement for NextFontLocalCssModuleReplacer {
|
impl ImportMappingReplacement for NextFontLocalCssModuleReplacer {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn replace(&self, _capture: &str) -> ImportMappingVc {
|
fn replace(&self, _capture: String) -> Vc<ImportMapping> {
|
||||||
ImportMapping::Ignore.into()
|
ImportMapping::Ignore.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,9 +151,9 @@ impl ImportMappingReplacement for NextFontLocalCssModuleReplacer {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn result(
|
async fn result(
|
||||||
&self,
|
&self,
|
||||||
context: FileSystemPathVc,
|
context: Vc<FileSystemPath>,
|
||||||
request: RequestVc,
|
request: Vc<Request>,
|
||||||
) -> Result<ImportMapResultVc> {
|
) -> Result<Vc<ImportMapResult>> {
|
||||||
let request = &*request.await?;
|
let request = &*request.await?;
|
||||||
let Request::Module {
|
let Request::Module {
|
||||||
module: _,
|
module: _,
|
||||||
|
@ -173,7 +166,7 @@ impl ImportMappingReplacement for NextFontLocalCssModuleReplacer {
|
||||||
|
|
||||||
let options = font_options_from_query_map(*query_vc);
|
let options = font_options_from_query_map(*query_vc);
|
||||||
let request_hash = get_request_hash(*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",
|
"/{}.module.css",
|
||||||
get_request_id(options.font_family(), request_hash).await?
|
get_request_id(options.font_family(), request_hash).await?
|
||||||
));
|
));
|
||||||
|
@ -187,26 +180,26 @@ impl ImportMappingReplacement for NextFontLocalCssModuleReplacer {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let css_asset = VirtualSourceVc::new(
|
let css_asset = VirtualSource::new(
|
||||||
css_virtual_path,
|
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]
|
#[turbo_tasks::function]
|
||||||
async fn get_font_css_properties(
|
async fn get_font_css_properties(
|
||||||
options_vc: NextFontLocalOptionsVc,
|
options_vc: Vc<NextFontLocalOptions>,
|
||||||
font_fallbacks: FontFallbacksVc,
|
font_fallbacks: Vc<FontFallbacks>,
|
||||||
request_hash: U32Vc,
|
request_hash: Vc<u32>,
|
||||||
) -> Result<FontCssPropertiesVc> {
|
) -> Result<Vc<FontCssProperties>> {
|
||||||
let options = &*options_vc.await?;
|
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),
|
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,
|
FontDescriptors::Many(_) => None,
|
||||||
// When the user only provided a top-level font file, include the font weight in the
|
// When the user only provided a top-level font file, include the font weight in the
|
||||||
// className selector rules
|
// className selector rules
|
||||||
|
@ -218,18 +211,18 @@ async fn get_font_css_properties(
|
||||||
.filter(|w| !matches!(w, FontWeight::Variable(_, _)))
|
.filter(|w| !matches!(w, FontWeight::Variable(_, _)))
|
||||||
.map(|w| w.to_string()),
|
.map(|w| w.to_string()),
|
||||||
}),
|
}),
|
||||||
style: OptionStringVc::cell(match &options.fonts {
|
style: Vc::cell(match &options.fonts {
|
||||||
FontDescriptors::Many(_) => None,
|
FontDescriptors::Many(_) => None,
|
||||||
// When the user only provided a top-level font file, include the font style in the
|
// When the user only provided a top-level font file, include the font style in the
|
||||||
// className selector rules
|
// className selector rules
|
||||||
FontDescriptors::One(descriptor) => descriptor.style.clone(),
|
FontDescriptors::One(descriptor) => descriptor.style.clone(),
|
||||||
}),
|
}),
|
||||||
variable: OptionStringVc::cell(options.variable.clone()),
|
variable: Vc::cell(options.variable.clone()),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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?;
|
let query_map = &*query.await?;
|
||||||
// These are invariants from the next/font swc transform. Regular errors instead
|
// These are invariants from the next/font swc transform. Regular errors instead
|
||||||
// of Issues should be okay.
|
// 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)?)
|
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 anyhow::{Context, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
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::{
|
use super::request::{
|
||||||
AdjustFontFallback, NextFontLocalRequest, NextFontLocalRequestArguments, SrcDescriptor,
|
AdjustFontFallback, NextFontLocalRequest, NextFontLocalRequestArguments, SrcDescriptor,
|
||||||
|
@ -34,15 +35,15 @@ pub(super) struct NextFontLocalOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextFontLocalOptionsVc {
|
impl NextFontLocalOptions {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(options: Value<NextFontLocalOptions>) -> NextFontLocalOptionsVc {
|
pub fn new(options: Value<NextFontLocalOptions>) -> Vc<NextFontLocalOptions> {
|
||||||
Self::cell(options.into_value())
|
Self::cell(options.into_value())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn font_family(self) -> Result<StringVc> {
|
pub async fn font_family(self: Vc<Self>) -> Result<Vc<String>> {
|
||||||
Ok(StringVc::cell((*self.await?.variable_name).to_owned()))
|
Ok(Vc::cell((*self.await?.variable_name).to_owned()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use indoc::formatdoc;
|
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::{
|
use crate::next_font::{
|
||||||
font_fallback::FontFallbacksVc,
|
font_fallback::FontFallbacks,
|
||||||
stylesheet::{build_fallback_definition, build_font_class_rules},
|
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]
|
#[turbo_tasks::function]
|
||||||
pub(super) async fn build_stylesheet(
|
pub(super) async fn build_stylesheet(
|
||||||
options: NextFontLocalOptionsVc,
|
options: Vc<NextFontLocalOptions>,
|
||||||
fallbacks: FontFallbacksVc,
|
fallbacks: Vc<FontFallbacks>,
|
||||||
css_properties: FontCssPropertiesVc,
|
css_properties: Vc<FontCssProperties>,
|
||||||
request_hash: U32Vc,
|
request_hash: Vc<u32>,
|
||||||
) -> Result<StringVc> {
|
) -> Result<Vc<String>> {
|
||||||
let scoped_font_family = get_scoped_font_family(
|
let scoped_font_family = get_scoped_font_family(
|
||||||
FontFamilyType::WebFont.cell(),
|
FontFamilyType::WebFont.cell(),
|
||||||
options.font_family(),
|
options.font_family(),
|
||||||
request_hash,
|
request_hash,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(StringVc::cell(formatdoc!(
|
Ok(Vc::cell(formatdoc!(
|
||||||
r#"
|
r#"
|
||||||
{}
|
{}
|
||||||
{}
|
{}
|
||||||
|
@ -37,9 +37,9 @@ pub(super) async fn build_stylesheet(
|
||||||
/// Builds a string of `@font-face` definitions for each local font file
|
/// Builds a string of `@font-face` definitions for each local font file
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) async fn build_font_face_definitions(
|
pub(super) async fn build_font_face_definitions(
|
||||||
scoped_font_family: StringVc,
|
scoped_font_family: Vc<String>,
|
||||||
options: NextFontLocalOptionsVc,
|
options: Vc<NextFontLocalOptions>,
|
||||||
) -> Result<StringVc> {
|
) -> Result<Vc<String>> {
|
||||||
let options = &*options.await?;
|
let options = &*options.await?;
|
||||||
|
|
||||||
let mut definitions = String::new();
|
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`
|
/// Used as e.g. `format('woff')` in `src` properties in `@font-face`
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
use anyhow::Result;
|
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::{
|
use crate::next_font::{
|
||||||
font_fallback::{FontFallback, FontFallbacksVc},
|
font_fallback::{FontFallback, FontFallbacks},
|
||||||
util::{get_scoped_font_family, FontFamilyType},
|
util::{get_scoped_font_family, FontFamilyType},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Returns a string to be used as the `font-family` property in css.
|
/// Returns a string to be used as the `font-family` property in css.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) async fn build_font_family_string(
|
pub(super) async fn build_font_family_string(
|
||||||
options: NextFontLocalOptionsVc,
|
options: Vc<NextFontLocalOptions>,
|
||||||
font_fallbacks: FontFallbacksVc,
|
font_fallbacks: Vc<FontFallbacks>,
|
||||||
request_hash: U32Vc,
|
request_hash: Vc<u32>,
|
||||||
) -> Result<StringVc> {
|
) -> Result<Vc<String>> {
|
||||||
let mut font_families = vec![format!(
|
let mut font_families = vec![format!(
|
||||||
"'{}'",
|
"'{}'",
|
||||||
*get_scoped_font_family(
|
*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 anyhow::Result;
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
use turbopack_binding::turbo::tasks::primitives::StringVc;
|
use turbo_tasks::Vc;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
font_fallback::{FontFallback, FontFallbacksVc},
|
font_fallback::{FontFallback, FontFallbacks},
|
||||||
util::FontCssPropertiesVc,
|
util::FontCssProperties,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Builds `@font-face` stylesheet definition for a given FontFallback
|
/// Builds `@font-face` stylesheet definition for a given FontFallback
|
||||||
#[turbo_tasks::function]
|
#[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();
|
let mut res = "".to_owned();
|
||||||
for fallback_vc in &*fallbacks.await? {
|
for fallback_vc in &*fallbacks.await? {
|
||||||
if let FontFallback::Automatic(fallback) = &*fallback_vc.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]
|
#[turbo_tasks::function]
|
||||||
pub(super) async fn build_font_class_rules(
|
pub(super) async fn build_font_class_rules(
|
||||||
css_properties: FontCssPropertiesVc,
|
css_properties: Vc<FontCssProperties>,
|
||||||
) -> Result<StringVc> {
|
) -> Result<Vc<String>> {
|
||||||
let css_properties = &*css_properties.await?;
|
let css_properties = &*css_properties.await?;
|
||||||
let font_family_string = &*css_properties.font_family.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 {
|
fn format_fixed_percentage(value: f64) -> String {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use turbo_tasks::primitives::{OptionStringVc, StringVc, U32Vc};
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
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
|
/// CSS properties and values for a given font variation. These are rendered as
|
||||||
|
@ -9,17 +9,17 @@ use turbopack_binding::{
|
||||||
/// module.
|
/// module.
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub(crate) struct FontCssProperties {
|
pub(crate) struct FontCssProperties {
|
||||||
pub font_family: StringVc,
|
pub font_family: Vc<String>,
|
||||||
pub weight: OptionStringVc,
|
pub weight: Vc<Option<String>>,
|
||||||
pub style: OptionStringVc,
|
pub style: Vc<Option<String>>,
|
||||||
pub variable: OptionStringVc,
|
pub variable: Vc<Option<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A hash of the requested querymap derived from how the user invoked
|
/// A hash of the requested querymap derived from how the user invoked
|
||||||
/// next/font. Used to uniquely identify font requests for generated filenames
|
/// next/font. Used to uniquely identify font requests for generated filenames
|
||||||
/// and scoped font family names.
|
/// and scoped font family names.
|
||||||
#[turbo_tasks::function]
|
#[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_vc.await?;
|
||||||
let query = query.as_ref().context("Query map must be present")?;
|
let query = query.as_ref().context("Query map must be present")?;
|
||||||
let mut to_hash = vec![];
|
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);
|
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
|
// Truncate the hash to u32. These hashes are ultimately displayed as 6- or 8-character
|
||||||
// hexadecimal values.
|
// hexadecimal values.
|
||||||
hash_xxh3_hash64(to_hash) as u32,
|
hash_xxh3_hash64(to_hash) as u32,
|
||||||
|
@ -48,10 +48,10 @@ pub(crate) enum FontFamilyType {
|
||||||
/// * `request_hash` - The hash value of the font request
|
/// * `request_hash` - The hash value of the font request
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(crate) async fn get_scoped_font_family(
|
pub(crate) async fn get_scoped_font_family(
|
||||||
ty: FontFamilyTypeVc,
|
ty: Vc<FontFamilyType>,
|
||||||
font_family_name: StringVc,
|
font_family_name: Vc<String>,
|
||||||
request_hash: U32Vc,
|
request_hash: Vc<u32>,
|
||||||
) -> Result<StringVc> {
|
) -> Result<Vc<String>> {
|
||||||
let hash = {
|
let hash = {
|
||||||
let mut hash = format!("{:x?}", request_hash.await?);
|
let mut hash = format!("{:x?}", request_hash.await?);
|
||||||
hash.truncate(6);
|
hash.truncate(6);
|
||||||
|
@ -64,13 +64,13 @@ pub(crate) async fn get_scoped_font_family(
|
||||||
FontFamilyType::Fallback => format!("{}_Fallback", font_family_base),
|
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]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_request_id(font_family: StringVc, request_hash: U32Vc) -> Result<StringVc> {
|
pub async fn get_request_id(font_family: Vc<String>, request_hash: Vc<u32>) -> Result<Vc<String>> {
|
||||||
Ok(StringVc::cell(format!(
|
Ok(Vc::cell(format!(
|
||||||
"{}_{:x?}",
|
"{}_{:x?}",
|
||||||
font_family.await?.to_lowercase().replace(' ', "_"),
|
font_family.await?.to_lowercase().replace(' ', "_"),
|
||||||
request_hash.await?
|
request_hash.await?
|
||||||
|
|
|
@ -1,24 +1,17 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use turbo_tasks::{primitives::StringVc, Value};
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbo_tasks_fs::FileSystem;
|
use turbo_tasks_fs::FileSystem;
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::AssetContent,
|
asset::AssetContent, ident::AssetIdent, introspect::Introspectable,
|
||||||
ident::AssetIdentVc,
|
server_fs::ServerFileSystem, version::VersionedContent,
|
||||||
introspect::{Introspectable, IntrospectableVc},
|
|
||||||
server_fs::ServerFileSystemVc,
|
|
||||||
version::VersionedContent,
|
|
||||||
},
|
},
|
||||||
dev_server::source::{
|
dev_server::source::{
|
||||||
query::QueryValue,
|
query::QueryValue,
|
||||||
route_tree::{RouteTreeVc, RouteType},
|
route_tree::{RouteTree, RouteType},
|
||||||
wrapping_source::{
|
wrapping_source::{ContentSourceProcessor, WrappedGetContentSourceContent},
|
||||||
ContentSourceProcessor, ContentSourceProcessorVc, WrappedGetContentSourceContentVc,
|
ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataFilter,
|
||||||
},
|
ContentSourceDataVary, GetContentSourceContent, ProxyResult, RewriteBuilder,
|
||||||
ContentSource, ContentSourceContent, ContentSourceContentVc, ContentSourceData,
|
|
||||||
ContentSourceDataFilter, ContentSourceDataVary, ContentSourceDataVaryVc, ContentSourceVc,
|
|
||||||
GetContentSourceContent, GetContentSourceContentVc, GetContentSourceContentsVc,
|
|
||||||
ProxyResult, RewriteBuilder,
|
|
||||||
},
|
},
|
||||||
image::process::optimize,
|
image::process::optimize,
|
||||||
};
|
};
|
||||||
|
@ -27,13 +20,13 @@ use turbopack_binding::turbopack::{
|
||||||
/// next/image.
|
/// next/image.
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextImageContentSource {
|
pub struct NextImageContentSource {
|
||||||
asset_source: ContentSourceVc,
|
asset_source: Vc<Box<dyn ContentSource>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextImageContentSourceVc {
|
impl NextImageContentSource {
|
||||||
#[turbo_tasks::function]
|
#[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()
|
NextImageContentSource { asset_source }.cell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,15 +34,15 @@ impl NextImageContentSourceVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ContentSource for NextImageContentSource {
|
impl ContentSource for NextImageContentSource {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn get_routes(self_vc: NextImageContentSourceVc) -> RouteTreeVc {
|
fn get_routes(self: Vc<Self>) -> Vc<RouteTree> {
|
||||||
RouteTreeVc::new_route(Vec::new(), RouteType::Exact, self_vc.into())
|
RouteTree::new_route(Vec::new(), RouteType::Exact, Vc::upcast(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl GetContentSourceContent for NextImageContentSource {
|
impl GetContentSourceContent for NextImageContentSource {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn vary(&self) -> ContentSourceDataVaryVc {
|
async fn vary(&self) -> Vc<ContentSourceDataVary> {
|
||||||
ContentSourceDataVary {
|
ContentSourceDataVary {
|
||||||
query: Some(ContentSourceDataFilter::Subset(
|
query: Some(ContentSourceDataFilter::Subset(
|
||||||
["url".to_string(), "w".to_string(), "q".to_string()].into(),
|
["url".to_string(), "w".to_string(), "q".to_string()].into(),
|
||||||
|
@ -61,11 +54,11 @@ impl GetContentSourceContent for NextImageContentSource {
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn get(
|
async fn get(
|
||||||
self_vc: NextImageContentSourceVc,
|
self: Vc<Self>,
|
||||||
_path: &str,
|
_path: String,
|
||||||
data: Value<ContentSourceData>,
|
data: Value<ContentSourceData>,
|
||||||
) -> Result<ContentSourceContentVc> {
|
) -> Result<Vc<ContentSourceContent>> {
|
||||||
let this = self_vc.await?;
|
let this = self.await?;
|
||||||
|
|
||||||
let Some(query) = &data.query else {
|
let Some(query) = &data.query else {
|
||||||
bail!("missing query");
|
bail!("missing query");
|
||||||
|
@ -99,18 +92,17 @@ impl GetContentSourceContent for NextImageContentSource {
|
||||||
// TODO: re-encode into next-gen formats.
|
// TODO: re-encode into next-gen formats.
|
||||||
|
|
||||||
if let Some(path) = url.strip_prefix('/') {
|
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
|
let sources = sources
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| {
|
.map(|s| {
|
||||||
WrappedGetContentSourceContentVc::new(
|
Vc::upcast(WrappedGetContentSourceContent::new(
|
||||||
*s,
|
*s,
|
||||||
NextImageContentSourceProcessorVc::new(path.to_string(), w, q).into(),
|
Vc::upcast(NextImageContentSourceProcessor::new(path.to_string(), w, q)),
|
||||||
)
|
))
|
||||||
.into()
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let sources = GetContentSourceContentsVc::cell(sources);
|
let sources = Vc::cell(sources);
|
||||||
return Ok(
|
return Ok(
|
||||||
ContentSourceContent::Rewrite(RewriteBuilder::new_sources(sources).build()).cell(),
|
ContentSourceContent::Rewrite(RewriteBuilder::new_sources(sources).build()).cell(),
|
||||||
);
|
);
|
||||||
|
@ -132,13 +124,13 @@ impl GetContentSourceContent for NextImageContentSource {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Introspectable for NextImageContentSource {
|
impl Introspectable for NextImageContentSource {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ty(&self) -> StringVc {
|
fn ty(&self) -> Vc<String> {
|
||||||
StringVc::cell("next image content source".to_string())
|
Vc::cell("next image content source".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn details(&self) -> StringVc {
|
fn details(&self) -> Vc<String> {
|
||||||
StringVc::cell("supports dynamic serving of any statically imported image".to_string())
|
Vc::cell("supports dynamic serving of any statically imported image".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,9 +142,9 @@ struct NextImageContentSourceProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextImageContentSourceProcessorVc {
|
impl NextImageContentSourceProcessor {
|
||||||
#[turbo_tasks::function]
|
#[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 {
|
NextImageContentSourceProcessor {
|
||||||
path,
|
path,
|
||||||
width,
|
width,
|
||||||
|
@ -165,7 +157,7 @@ impl NextImageContentSourceProcessorVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ContentSourceProcessor for NextImageContentSourceProcessor {
|
impl ContentSourceProcessor for NextImageContentSourceProcessor {
|
||||||
#[turbo_tasks::function]
|
#[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 {
|
let ContentSourceContent::Static(static_content) = *content.await? else {
|
||||||
return Ok(content);
|
return Ok(content);
|
||||||
};
|
};
|
||||||
|
@ -175,13 +167,13 @@ impl ContentSourceProcessor for NextImageContentSourceProcessor {
|
||||||
return Ok(content);
|
return Ok(content);
|
||||||
};
|
};
|
||||||
let optimized_file_content = optimize(
|
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,
|
file_content,
|
||||||
self.width,
|
self.width,
|
||||||
u32::MAX,
|
u32::MAX,
|
||||||
self.quality,
|
self.quality,
|
||||||
);
|
);
|
||||||
Ok(ContentSourceContentVc::static_content(
|
Ok(ContentSourceContent::static_content(
|
||||||
AssetContent::File(optimized_file_content).into(),
|
AssetContent::File(optimized_file_content).into(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,5 +2,5 @@ pub(crate) mod content_source;
|
||||||
pub(crate) mod module;
|
pub(crate) mod module;
|
||||||
pub(crate) mod source_asset;
|
pub(crate) mod source_asset;
|
||||||
|
|
||||||
pub use content_source::NextImageContentSourceVc;
|
pub use content_source::NextImageContentSource;
|
||||||
pub use module::StructuredImageModuleTypeVc;
|
pub use module::StructuredImageModuleType;
|
||||||
|
|
|
@ -1,20 +1,14 @@
|
||||||
use anyhow::Result;
|
|
||||||
use indexmap::indexmap;
|
use indexmap::indexmap;
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks::Value,
|
turbo::tasks::Value,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
context::AssetContext,
|
context::AssetContext, module::Module, reference_type::ReferenceType,
|
||||||
module::ModuleVc,
|
resolve::ModulePart, source::Source,
|
||||||
reference_type::{InnerAssetsVc, ReferenceType},
|
|
||||||
resolve::ModulePartVc,
|
|
||||||
source::SourceVc,
|
|
||||||
},
|
|
||||||
r#static::StaticModuleAssetVc,
|
|
||||||
turbopack::{
|
|
||||||
module_options::{CustomModuleType, CustomModuleTypeVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
},
|
||||||
|
r#static::StaticModuleAsset,
|
||||||
|
turbopack::{module_options::CustomModuleType, ModuleAssetContext},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,30 +39,31 @@ pub struct StructuredImageModuleType {
|
||||||
|
|
||||||
impl StructuredImageModuleType {
|
impl StructuredImageModuleType {
|
||||||
pub(crate) fn create_module(
|
pub(crate) fn create_module(
|
||||||
source: SourceVc,
|
source: Vc<Box<dyn Source>>,
|
||||||
blur_placeholder_mode: BlurPlaceholderMode,
|
blur_placeholder_mode: BlurPlaceholderMode,
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
) -> ModuleVc {
|
) -> Vc<Box<dyn Module>> {
|
||||||
let static_asset = StaticModuleAssetVc::new(source, context.into());
|
let static_asset = StaticModuleAsset::new(source, Vc::upcast(context));
|
||||||
context.process(
|
context.process(
|
||||||
StructuredImageFileSource {
|
Vc::upcast(
|
||||||
image: source,
|
StructuredImageFileSource {
|
||||||
blur_placeholder_mode,
|
image: source,
|
||||||
}
|
blur_placeholder_mode,
|
||||||
.cell()
|
}
|
||||||
.into(),
|
.cell(),
|
||||||
Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap!(
|
),
|
||||||
"IMAGE".to_string() => static_asset.into()
|
Value::new(ReferenceType::Internal(Vc::cell(indexmap!(
|
||||||
|
"IMAGE".to_string() => Vc::upcast(static_asset)
|
||||||
)))),
|
)))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl StructuredImageModuleTypeVc {
|
impl StructuredImageModuleType {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(blur_placeholder_mode: Value<BlurPlaceholderMode>) -> Self {
|
pub fn new(blur_placeholder_mode: Value<BlurPlaceholderMode>) -> Vc<Self> {
|
||||||
StructuredImageModuleTypeVc::cell(StructuredImageModuleType {
|
StructuredImageModuleType::cell(StructuredImageModuleType {
|
||||||
blur_placeholder_mode: blur_placeholder_mode.into_value(),
|
blur_placeholder_mode: blur_placeholder_mode.into_value(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -79,10 +74,10 @@ impl CustomModuleType for StructuredImageModuleType {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn create_module(
|
fn create_module(
|
||||||
&self,
|
&self,
|
||||||
source: SourceVc,
|
source: Vc<Box<dyn Source>>,
|
||||||
context: ModuleAssetContextVc,
|
context: Vc<ModuleAssetContext>,
|
||||||
_part: Option<ModulePartVc>,
|
_part: Option<Vc<ModulePart>>,
|
||||||
) -> ModuleVc {
|
) -> Vc<Box<dyn Module>> {
|
||||||
StructuredImageModuleType::create_module(source, self.blur_placeholder_mode, context)
|
StructuredImageModuleType::create_module(source, self.blur_placeholder_mode, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,28 @@
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{
|
turbo::tasks_fs::{rope::RopeBuilder, FileContent},
|
||||||
tasks::primitives::StringVc,
|
|
||||||
tasks_fs::{rope::RopeBuilder, FileContent},
|
|
||||||
},
|
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetContent, AssetContentVc, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
ident::AssetIdentVc,
|
ident::AssetIdent,
|
||||||
source::{Source, SourceVc},
|
source::Source,
|
||||||
},
|
},
|
||||||
ecmascript::utils::StringifyJs,
|
ecmascript::utils::StringifyJs,
|
||||||
image::process::{get_meta_data, BlurPlaceholderOptions, BlurPlaceholderOptionsVc},
|
image::process::{get_meta_data, BlurPlaceholderOptions},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::module::BlurPlaceholderMode;
|
use super::module::BlurPlaceholderMode;
|
||||||
|
|
||||||
fn modifier() -> StringVc {
|
fn modifier() -> Vc<String> {
|
||||||
StringVc::cell("structured image object".to_string())
|
Vc::cell("structured image object".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn blur_options() -> BlurPlaceholderOptionsVc {
|
fn blur_options() -> Vc<BlurPlaceholderOptions> {
|
||||||
BlurPlaceholderOptions {
|
BlurPlaceholderOptions {
|
||||||
quality: 70,
|
quality: 70,
|
||||||
size: 8,
|
size: 8,
|
||||||
|
@ -36,7 +34,7 @@ fn blur_options() -> BlurPlaceholderOptionsVc {
|
||||||
/// an object with meta information like width, height and a blur placeholder.
|
/// an object with meta information like width, height and a blur placeholder.
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct StructuredImageFileSource {
|
pub struct StructuredImageFileSource {
|
||||||
pub image: SourceVc,
|
pub image: Vc<Box<dyn Source>>,
|
||||||
pub blur_placeholder_mode: BlurPlaceholderMode,
|
pub blur_placeholder_mode: BlurPlaceholderMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,15 +44,15 @@ impl Source for StructuredImageFileSource {}
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Asset for StructuredImageFileSource {
|
impl Asset for StructuredImageFileSource {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ident(&self) -> AssetIdentVc {
|
fn ident(&self) -> Vc<AssetIdent> {
|
||||||
self.image
|
self.image
|
||||||
.ident()
|
.ident()
|
||||||
.with_modifier(modifier())
|
.with_modifier(modifier())
|
||||||
.rename_as("*.mjs")
|
.rename_as("*.mjs".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn content(&self) -> Result<AssetContentVc> {
|
async fn content(&self) -> Result<Vc<AssetContent>> {
|
||||||
let content = self.image.content().await?;
|
let content = self.image.content().await?;
|
||||||
let AssetContent::File(content) = *content else {
|
let AssetContent::File(content) = *content else {
|
||||||
bail!("Input source is not a file and can't be transformed into image information");
|
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 std::collections::{BTreeMap, HashMap};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use turbo_tasks::Value;
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::{glob::GlobVc, FileSystem, FileSystemPathVc},
|
turbo::tasks_fs::{glob::Glob, FileSystem, FileSystemPath},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::Asset,
|
asset::Asset,
|
||||||
resolve::{
|
resolve::{
|
||||||
options::{
|
options::{ConditionValue, ImportMap, ImportMapping, ResolveOptions, ResolvedMap},
|
||||||
ConditionValue, ImportMap, ImportMapVc, ImportMapping, ImportMappingVc,
|
parse::Request,
|
||||||
ResolveOptionsVc, ResolvedMap, ResolvedMapVc,
|
|
||||||
},
|
|
||||||
parse::RequestVc,
|
|
||||||
pattern::Pattern,
|
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},
|
turbopack::{resolve_options, resolve_options_context::ResolveOptionsContext},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -26,10 +23,10 @@ use crate::{
|
||||||
embed_js::{next_js_fs, VIRTUAL_PACKAGE_NAME},
|
embed_js::{next_js_fs, VIRTUAL_PACKAGE_NAME},
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
next_client::context::ClientContextType,
|
next_client::context::ClientContextType,
|
||||||
next_config::NextConfigVc,
|
next_config::NextConfig,
|
||||||
next_font::{
|
next_font::{
|
||||||
google::{NextFontGoogleCssModuleReplacerVc, NextFontGoogleReplacerVc},
|
google::{NextFontGoogleCssModuleReplacer, NextFontGoogleReplacer},
|
||||||
local::{NextFontLocalCssModuleReplacerVc, NextFontLocalReplacerVc},
|
local::{NextFontLocalCssModuleReplacer, NextFontLocalReplacer},
|
||||||
},
|
},
|
||||||
next_server::context::ServerContextType,
|
next_server::context::ServerContextType,
|
||||||
};
|
};
|
||||||
|
@ -38,11 +35,11 @@ use crate::{
|
||||||
/// Computes the Next-specific client import map.
|
/// Computes the Next-specific client import map.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_next_client_import_map(
|
pub async fn get_next_client_import_map(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
ty: Value<ClientContextType>,
|
ty: Value<ClientContextType>,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
) -> Result<ImportMapVc> {
|
) -> Result<Vc<ImportMap>> {
|
||||||
let mut import_map = ImportMap::empty();
|
let mut import_map = ImportMap::empty();
|
||||||
|
|
||||||
insert_next_shared_aliases(
|
insert_next_shared_aliases(
|
||||||
|
@ -139,7 +136,7 @@ pub async fn get_next_client_import_map(
|
||||||
|
|
||||||
/// Computes the Next-specific client import map.
|
/// Computes the Next-specific client import map.
|
||||||
#[turbo_tasks::function]
|
#[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();
|
let mut import_map = ImportMap::empty();
|
||||||
|
|
||||||
insert_package_alias(
|
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
|
/// Computes the Next-specific client fallback import map, which provides
|
||||||
/// polyfills to Node.js externals.
|
/// polyfills to Node.js externals.
|
||||||
#[turbo_tasks::function]
|
#[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();
|
let mut import_map = ImportMap::empty();
|
||||||
|
|
||||||
match ty.into_value() {
|
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.
|
/// Computes the Next-specific server-side import map.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_next_server_import_map(
|
pub async fn get_next_server_import_map(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
ty: Value<ServerContextType>,
|
ty: Value<ServerContextType>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
) -> Result<ImportMapVc> {
|
) -> Result<Vc<ImportMap>> {
|
||||||
let mut import_map = ImportMap::empty();
|
let mut import_map = ImportMap::empty();
|
||||||
|
|
||||||
insert_next_shared_aliases(
|
insert_next_shared_aliases(
|
||||||
|
@ -253,12 +250,12 @@ pub async fn get_next_server_import_map(
|
||||||
/// Computes the Next-specific edge-side import map.
|
/// Computes the Next-specific edge-side import map.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_next_edge_import_map(
|
pub async fn get_next_edge_import_map(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
ty: Value<ServerContextType>,
|
ty: Value<ServerContextType>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
) -> Result<ImportMapVc> {
|
) -> Result<Vc<ImportMap>> {
|
||||||
let mut import_map = ImportMap::empty();
|
let mut import_map = ImportMap::empty();
|
||||||
|
|
||||||
insert_next_shared_aliases(
|
insert_next_shared_aliases(
|
||||||
|
@ -302,14 +299,17 @@ pub async fn get_next_edge_import_map(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_next_client_resolved_map(
|
pub fn get_next_client_resolved_map(
|
||||||
context: FileSystemPathVc,
|
context: Vc<FileSystemPath>,
|
||||||
root: FileSystemPathVc,
|
root: Vc<FileSystemPath>,
|
||||||
) -> ResolvedMapVc {
|
) -> Vc<ResolvedMap> {
|
||||||
let glob_mappings = vec![
|
let glob_mappings = vec![
|
||||||
// Temporary hack to replace the hot reloader until this is passable by props in next.js
|
// Temporary hack to replace the hot reloader until this is passable by props in next.js
|
||||||
(
|
(
|
||||||
context.root(),
|
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(
|
ImportMapping::PrimaryAlternative(
|
||||||
"@vercel/turbopack-next/dev/hot-reloader.tsx".to_string(),
|
"@vercel/turbopack-next/dev/hot-reloader.tsx".to_string(),
|
||||||
Some(root),
|
Some(root),
|
||||||
|
@ -515,9 +515,9 @@ pub fn mdx_import_source_file() -> String {
|
||||||
// Make sure to not add any external requests here.
|
// Make sure to not add any external requests here.
|
||||||
pub async fn insert_next_shared_aliases(
|
pub async fn insert_next_shared_aliases(
|
||||||
import_map: &mut ImportMap,
|
import_map: &mut ImportMap,
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let package_root = next_js_fs().root();
|
let package_root = next_js_fs().root();
|
||||||
|
|
||||||
|
@ -549,38 +549,42 @@ pub async fn insert_next_shared_aliases(
|
||||||
import_map.insert_alias(
|
import_map.insert_alias(
|
||||||
// Request path from js via next-font swc transform
|
// Request path from js via next-font swc transform
|
||||||
AliasPattern::exact("next/font/google/target.css"),
|
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(
|
import_map.insert_alias(
|
||||||
// Request path from js via next-font swc transform
|
// Request path from js via next-font swc transform
|
||||||
AliasPattern::exact("@next/font/google/target.css"),
|
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(
|
import_map.insert_alias(
|
||||||
AliasPattern::exact("@vercel/turbopack-next/internal/font/google/cssmodule.module.css"),
|
AliasPattern::exact("@vercel/turbopack-next/internal/font/google/cssmodule.module.css"),
|
||||||
ImportMapping::Dynamic(
|
ImportMapping::Dynamic(Vc::upcast(NextFontGoogleCssModuleReplacer::new(
|
||||||
NextFontGoogleCssModuleReplacerVc::new(project_path, execution_context).into(),
|
project_path,
|
||||||
)
|
execution_context,
|
||||||
|
)))
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
import_map.insert_alias(
|
import_map.insert_alias(
|
||||||
// Request path from js via next-font swc transform
|
// Request path from js via next-font swc transform
|
||||||
AliasPattern::exact("next/font/local/target.css"),
|
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(
|
import_map.insert_alias(
|
||||||
// Request path from js via next-font swc transform
|
// Request path from js via next-font swc transform
|
||||||
AliasPattern::exact("@next/font/local/target.css"),
|
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(
|
import_map.insert_alias(
|
||||||
AliasPattern::exact("@vercel/turbopack-next/internal/font/local/cssmodule.module.css"),
|
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));
|
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]
|
#[turbo_tasks::function]
|
||||||
async fn package_lookup_resolve_options(
|
async fn package_lookup_resolve_options(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
) -> Result<ResolveOptionsVc> {
|
) -> Result<Vc<ResolveOptions>> {
|
||||||
Ok(resolve_options(
|
Ok(resolve_options(
|
||||||
project_path,
|
project_path,
|
||||||
ResolveOptionsContext {
|
ResolveOptionsContext {
|
||||||
|
@ -616,10 +620,10 @@ async fn package_lookup_resolve_options(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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(
|
let result = resolve(
|
||||||
project_path,
|
project_path,
|
||||||
RequestVc::parse(Value::new(Pattern::Constant(
|
Request::parse(Value::new(Pattern::Constant(
|
||||||
"next/package.json".to_string(),
|
"next/package.json".to_string(),
|
||||||
))),
|
))),
|
||||||
package_lookup_resolve_options(project_path),
|
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>(
|
pub async fn insert_alias_option<const N: usize>(
|
||||||
import_map: &mut ImportMap,
|
import_map: &mut ImportMap,
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
alias_options: ResolveAliasMapVc,
|
alias_options: Vc<ResolveAliasMap>,
|
||||||
conditions: [&'static str; N],
|
conditions: [&'static str; N],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let conditions = BTreeMap::from(conditions.map(|c| (c.to_string(), ConditionValue::Set)));
|
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(
|
fn export_value_to_import_mapping(
|
||||||
value: &SubpathValue,
|
value: &SubpathValue,
|
||||||
conditions: &BTreeMap<String, ConditionValue>,
|
conditions: &BTreeMap<String, ConditionValue>,
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
) -> Option<ImportMappingVc> {
|
) -> Option<Vc<ImportMapping>> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
value.add_results(
|
value.add_results(
|
||||||
conditions,
|
conditions,
|
||||||
|
@ -679,13 +683,17 @@ fn export_value_to_import_mapping(
|
||||||
fn insert_alias_to_alternatives<'a>(
|
fn insert_alias_to_alternatives<'a>(
|
||||||
import_map: &mut ImportMap,
|
import_map: &mut ImportMap,
|
||||||
alias: impl Into<String> + 'a,
|
alias: impl Into<String> + 'a,
|
||||||
alternatives: Vec<ImportMappingVc>,
|
alternatives: Vec<Vc<ImportMapping>>,
|
||||||
) {
|
) {
|
||||||
import_map.insert_exact_alias(alias, ImportMapping::Alternatives(alternatives).into());
|
import_map.insert_exact_alias(alias, ImportMapping::Alternatives(alternatives).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts an alias to an import mapping into an import map.
|
/// 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(
|
import_map.insert_wildcard_alias(
|
||||||
prefix,
|
prefix,
|
||||||
ImportMapping::PrimaryAlternative("./*".to_string(), Some(package_root)).cell(),
|
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
|
/// Creates a direct import mapping to the result of resolving a request
|
||||||
/// in a context.
|
/// 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()
|
ImportMapping::PrimaryAlternative(request.to_string(), Some(context_path)).cell()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a direct import mapping to the result of resolving an external
|
/// Creates a direct import mapping to the result of resolving an external
|
||||||
/// request.
|
/// 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()
|
ImportMapping::External(Some(request.to_string())).into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::turbopack::node::route_matcher::{Params, RouteMatcherRef};
|
||||||
turbo::tasks::primitives::BoolVc,
|
|
||||||
turbopack::node::route_matcher::{ParamsVc, RouteMatcher},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
pub struct AllMatch;
|
pub struct AllMatch;
|
||||||
|
|
||||||
impl RouteMatcher for AllMatch {
|
impl RouteMatcherRef for AllMatch {
|
||||||
fn matches(&self, _path: &str) -> BoolVc {
|
fn matches(&self, _path: &str) -> bool {
|
||||||
BoolVc::cell(true)
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn params(&self, _path: &str) -> ParamsVc {
|
fn params(&self, _path: &str) -> Params {
|
||||||
ParamsVc::cell(Some(Default::default()))
|
Params(Some(Default::default()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use turbopack_binding::{
|
use turbo_tasks::Vc;
|
||||||
turbo::tasks::primitives::{BoolVc, StringVc},
|
use turbopack_binding::turbopack::node::route_matcher::{Params, RouteMatcher, RouteMatcherRef};
|
||||||
turbopack::node::route_matcher::{ParamsVc, RouteMatcher, RouteMatcherVc},
|
|
||||||
};
|
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
all::AllMatch,
|
all::AllMatch,
|
||||||
|
@ -17,13 +15,13 @@ mod prefix_suffix;
|
||||||
/// A route matcher that matches a path against an exact route.
|
/// A route matcher that matches a path against an exact route.
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub(crate) struct NextExactMatcher {
|
pub(crate) struct NextExactMatcher {
|
||||||
path: StringVc,
|
path: Vc<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextExactMatcherVc {
|
impl NextExactMatcher {
|
||||||
#[turbo_tasks::function]
|
#[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 }))
|
Ok(Self::cell(NextExactMatcher { path }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,13 +29,13 @@ impl NextExactMatcherVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl RouteMatcher for NextExactMatcher {
|
impl RouteMatcher for NextExactMatcher {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn matches(&self, path: &str) -> Result<BoolVc> {
|
async fn matches(&self, path: String) -> Result<Vc<bool>> {
|
||||||
Ok(BoolVc::cell(path == *self.path.await?))
|
Ok(Vc::cell(path == *self.path.await?))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn params(&self, path: &str) -> Result<ParamsVc> {
|
async fn params(&self, path: String) -> Result<Vc<Params>> {
|
||||||
Ok(ParamsVc::cell(if path == *self.path.await? {
|
Ok(Vc::cell(if path == *self.path.await? {
|
||||||
Some(Default::default())
|
Some(Default::default())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -53,9 +51,9 @@ pub(crate) struct NextParamsMatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextParamsMatcherVc {
|
impl NextParamsMatcher {
|
||||||
#[turbo_tasks::function]
|
#[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 {
|
Ok(Self::cell(NextParamsMatcher {
|
||||||
matcher: build_path_regex(path.await?.as_str())?,
|
matcher: build_path_regex(path.await?.as_str())?,
|
||||||
}))
|
}))
|
||||||
|
@ -65,13 +63,13 @@ impl NextParamsMatcherVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl RouteMatcher for NextParamsMatcher {
|
impl RouteMatcher for NextParamsMatcher {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn matches(&self, path: &str) -> BoolVc {
|
fn matches(&self, path: String) -> Vc<bool> {
|
||||||
self.matcher.matches(path)
|
Vc::cell(self.matcher.matches(&path))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn params(&self, path: &str) -> ParamsVc {
|
fn params(&self, path: String) -> Vc<Params> {
|
||||||
self.matcher.params(path)
|
Params::cell(self.matcher.params(&path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,11 +82,11 @@ pub(crate) struct NextPrefixSuffixParamsMatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextPrefixSuffixParamsMatcherVc {
|
impl NextPrefixSuffixParamsMatcher {
|
||||||
/// Converts a filename within the server root into a regular expression
|
/// Converts a filename within the server root into a regular expression
|
||||||
/// with named capture groups for every dynamic segment.
|
/// with named capture groups for every dynamic segment.
|
||||||
#[turbo_tasks::function]
|
#[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 {
|
Ok(Self::cell(NextPrefixSuffixParamsMatcher {
|
||||||
matcher: PrefixSuffixMatcher::new(
|
matcher: PrefixSuffixMatcher::new(
|
||||||
prefix.to_string(),
|
prefix.to_string(),
|
||||||
|
@ -102,13 +100,13 @@ impl NextPrefixSuffixParamsMatcherVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl RouteMatcher for NextPrefixSuffixParamsMatcher {
|
impl RouteMatcher for NextPrefixSuffixParamsMatcher {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn matches(&self, path: &str) -> BoolVc {
|
fn matches(&self, path: String) -> Vc<bool> {
|
||||||
self.matcher.matches(path)
|
Vc::cell(self.matcher.matches(&path))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn params(&self, path: &str) -> ParamsVc {
|
fn params(&self, path: String) -> Vc<Params> {
|
||||||
self.matcher.params(path)
|
Params::cell(self.matcher.params(&path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,9 +118,9 @@ pub(crate) struct NextFallbackMatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextFallbackMatcherVc {
|
impl NextFallbackMatcher {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Vc<Self> {
|
||||||
Self::cell(NextFallbackMatcher { matcher: AllMatch })
|
Self::cell(NextFallbackMatcher { matcher: AllMatch })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,13 +128,13 @@ impl NextFallbackMatcherVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl RouteMatcher for NextFallbackMatcher {
|
impl RouteMatcher for NextFallbackMatcher {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn matches(&self, path: &str) -> BoolVc {
|
fn matches(&self, path: String) -> Vc<bool> {
|
||||||
self.matcher.matches(path)
|
Vc::cell(self.matcher.matches(&path))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn params(&self, path: &str) -> ParamsVc {
|
fn params(&self, path: String) -> Vc<Params> {
|
||||||
self.matcher.params(path)
|
Params::cell(self.matcher.params(&path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks::primitives::{BoolVc, Regex},
|
turbo::tasks::primitives::Regex,
|
||||||
turbopack::node::route_matcher::{Param, ParamsVc, RouteMatcher},
|
turbopack::node::route_matcher::{Param, Params, RouteMatcherRef},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A regular expression that matches a path, with named capture groups for the
|
/// 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 {
|
impl RouteMatcherRef for PathRegex {
|
||||||
fn matches(&self, path: &str) -> BoolVc {
|
fn matches(&self, path: &str) -> bool {
|
||||||
BoolVc::cell(self.regex.is_match(path))
|
self.regex.is_match(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn params(&self, path: &str) -> ParamsVc {
|
fn params(&self, path: &str) -> Params {
|
||||||
ParamsVc::cell(self.regex.captures(path).map(|capture| {
|
Params(self.regex.captures(path).map(|capture| {
|
||||||
self.named_params
|
self.named_params
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::turbopack::node::route_matcher::{Params, RouteMatcherRef};
|
||||||
turbo::tasks::primitives::BoolVc,
|
|
||||||
turbopack::node::route_matcher::{ParamsVc, RouteMatcher},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A composite route matcher that matches a path if it has a given prefix and
|
/// A composite route matcher that matches a path if it has a given prefix and
|
||||||
/// suffix.
|
/// suffix.
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
pub struct PrefixSuffixMatcher<T>
|
pub struct PrefixSuffixMatcher<T>
|
||||||
where
|
where
|
||||||
T: RouteMatcher,
|
T: RouteMatcherRef,
|
||||||
{
|
{
|
||||||
prefix: String,
|
prefix: String,
|
||||||
suffix: String,
|
suffix: String,
|
||||||
|
@ -18,7 +15,7 @@ where
|
||||||
|
|
||||||
impl<T> PrefixSuffixMatcher<T>
|
impl<T> PrefixSuffixMatcher<T>
|
||||||
where
|
where
|
||||||
T: RouteMatcher,
|
T: RouteMatcherRef,
|
||||||
{
|
{
|
||||||
/// Creates a new [PrefixSuffixMatcher].
|
/// Creates a new [PrefixSuffixMatcher].
|
||||||
pub fn new(prefix: String, suffix: String, inner: T) -> Self {
|
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
|
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) {
|
if let Some(path) = self.strip_prefix_and_suffix(path) {
|
||||||
self.inner.matches(path)
|
self.inner.matches(path)
|
||||||
} else {
|
} 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) {
|
if let Some(path) = self.strip_prefix_and_suffix(path) {
|
||||||
self.inner.params(path)
|
self.inner.params(path)
|
||||||
} else {
|
} else {
|
||||||
ParamsVc::cell(None)
|
Params(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +1,38 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use turbo_tasks::{primitives::StringVc, Value};
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbo_tasks_fs::FileSystem;
|
use turbo_tasks_fs::FileSystem;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{tasks_env::ProcessEnvVc, tasks_fs::FileSystemPathVc},
|
turbo::{tasks_env::ProcessEnv, tasks_fs::FileSystemPath},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
build::BuildChunkingContextVc,
|
build::BuildChunkingContext,
|
||||||
core::{
|
core::{
|
||||||
compile_time_defines,
|
compile_time_defines,
|
||||||
compile_time_info::{
|
compile_time_info::{CompileTimeDefines, CompileTimeInfo, FreeVarReferences},
|
||||||
CompileTimeDefines, CompileTimeDefinesVc, CompileTimeInfo, CompileTimeInfoVc,
|
environment::{Environment, ExecutionEnvironment, NodeJsEnvironment, ServerAddr},
|
||||||
FreeVarReferencesVc,
|
|
||||||
},
|
|
||||||
environment::{EnvironmentVc, ExecutionEnvironment, NodeJsEnvironmentVc, ServerAddrVc},
|
|
||||||
free_var_references,
|
free_var_references,
|
||||||
resolve::{parse::RequestVc, pattern::Pattern},
|
resolve::{parse::Request, pattern::Pattern},
|
||||||
},
|
},
|
||||||
ecmascript::TransformPluginVc,
|
ecmascript::TransformPlugin,
|
||||||
ecmascript_plugin::transform::directives::{
|
ecmascript_plugin::transform::directives::{
|
||||||
client::ClientDirectiveTransformer, server::ServerDirectiveTransformer,
|
client::ClientDirectiveTransformer, server::ServerDirectiveTransformer,
|
||||||
},
|
},
|
||||||
env::ProcessEnvAssetVc,
|
env::ProcessEnvAsset,
|
||||||
node::execution_context::ExecutionContextVc,
|
node::execution_context::ExecutionContext,
|
||||||
turbopack::{
|
turbopack::{
|
||||||
condition::ContextCondition,
|
condition::ContextCondition,
|
||||||
module_options::{
|
module_options::{
|
||||||
CustomEcmascriptTransformPlugins, CustomEcmascriptTransformPluginsVc,
|
CustomEcmascriptTransformPlugins, JsxTransformOptions, MdxTransformModuleOptions,
|
||||||
JsxTransformOptions, MdxTransformModuleOptions, ModuleOptionsContext,
|
ModuleOptionsContext, PostCssTransformOptions, TypescriptTransformOptions,
|
||||||
ModuleOptionsContextVc, PostCssTransformOptions, TypescriptTransformOptions,
|
|
||||||
WebpackLoadersOptions,
|
WebpackLoadersOptions,
|
||||||
},
|
},
|
||||||
resolve_options_context::{ResolveOptionsContext, ResolveOptionsContextVc},
|
resolve_options_context::ResolveOptionsContext,
|
||||||
transition::TransitionVc,
|
transition::Transition,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
resolve::ExternalCjsModulesResolvePluginVc,
|
resolve::ExternalCjsModulesResolvePlugin,
|
||||||
transforms::{get_next_server_internal_transforms_rules, get_next_server_transforms_rules},
|
transforms::{get_next_server_internal_transforms_rules, get_next_server_transforms_rules},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -45,12 +41,12 @@ use crate::{
|
||||||
env::env_for_js,
|
env::env_for_js,
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
next_build::{get_external_next_compiled_package_mapping, get_postcss_package_mapping},
|
next_build::{get_external_next_compiled_package_mapping, get_postcss_package_mapping},
|
||||||
next_client::{RuntimeEntriesVc, RuntimeEntry},
|
next_client::{RuntimeEntries, RuntimeEntry},
|
||||||
next_config::NextConfigVc,
|
next_config::NextConfig,
|
||||||
next_import_map::{get_next_server_import_map, mdx_import_source_file},
|
next_import_map::{get_next_server_import_map, mdx_import_source_file},
|
||||||
next_server::resolve::ExternalPredicate,
|
next_server::resolve::ExternalPredicate,
|
||||||
next_shared::{
|
next_shared::{
|
||||||
resolve::UnsupportedModulesResolvePluginVc,
|
resolve::UnsupportedModulesResolvePlugin,
|
||||||
transforms::{
|
transforms::{
|
||||||
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
|
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
|
||||||
styled_components::get_styled_components_transform_plugin,
|
styled_components::get_styled_components_transform_plugin,
|
||||||
|
@ -70,46 +66,46 @@ use crate::{
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord)]
|
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord)]
|
||||||
pub enum ServerContextType {
|
pub enum ServerContextType {
|
||||||
Pages {
|
Pages {
|
||||||
pages_dir: FileSystemPathVc,
|
pages_dir: Vc<FileSystemPath>,
|
||||||
},
|
},
|
||||||
PagesData {
|
PagesData {
|
||||||
pages_dir: FileSystemPathVc,
|
pages_dir: Vc<FileSystemPath>,
|
||||||
},
|
},
|
||||||
AppSSR {
|
AppSSR {
|
||||||
app_dir: FileSystemPathVc,
|
app_dir: Vc<FileSystemPath>,
|
||||||
},
|
},
|
||||||
AppRSC {
|
AppRSC {
|
||||||
app_dir: FileSystemPathVc,
|
app_dir: Vc<FileSystemPath>,
|
||||||
ecmascript_client_reference_transition_name: Option<StringVc>,
|
ecmascript_client_reference_transition_name: Option<Vc<String>>,
|
||||||
client_transition: Option<TransitionVc>,
|
client_transition: Option<Vc<Box<dyn Transition>>>,
|
||||||
},
|
},
|
||||||
AppRoute {
|
AppRoute {
|
||||||
app_dir: FileSystemPathVc,
|
app_dir: Vc<FileSystemPath>,
|
||||||
},
|
},
|
||||||
Middleware,
|
Middleware,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_server_resolve_options_context(
|
pub async fn get_server_resolve_options_context(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
ty: Value<ServerContextType>,
|
ty: Value<ServerContextType>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
) -> Result<ResolveOptionsContextVc> {
|
) -> Result<Vc<ResolveOptionsContext>> {
|
||||||
let next_server_import_map =
|
let next_server_import_map =
|
||||||
get_next_server_import_map(project_path, ty, mode, next_config, execution_context);
|
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 foreign_code_context_condition = foreign_code_context_condition(next_config).await?;
|
||||||
let root_dir = project_path.root().resolve().await?;
|
let root_dir = project_path.root().resolve().await?;
|
||||||
let unsupported_modules_resolve_plugin = UnsupportedModulesResolvePluginVc::new(project_path);
|
let unsupported_modules_resolve_plugin = UnsupportedModulesResolvePlugin::new(project_path);
|
||||||
let server_component_externals_plugin = ExternalCjsModulesResolvePluginVc::new(
|
let server_component_externals_plugin = ExternalCjsModulesResolvePlugin::new(
|
||||||
project_path,
|
project_path,
|
||||||
ExternalPredicate::Only(next_config.server_component_externals()).cell(),
|
ExternalPredicate::Only(next_config.server_component_externals()).cell(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(match ty.into_value() {
|
Ok(match ty.into_value() {
|
||||||
ServerContextType::Pages { .. } | ServerContextType::PagesData { .. } => {
|
ServerContextType::Pages { .. } | ServerContextType::PagesData { .. } => {
|
||||||
let external_cjs_modules_plugin = ExternalCjsModulesResolvePluginVc::new(
|
let external_cjs_modules_plugin = ExternalCjsModulesResolvePlugin::new(
|
||||||
project_path,
|
project_path,
|
||||||
ExternalPredicate::AllExcept(next_config.transpile_packages()).cell(),
|
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()],
|
custom_conditions: vec![mode.node_env().to_string(), "node".to_string()],
|
||||||
import_map: Some(next_server_import_map),
|
import_map: Some(next_server_import_map),
|
||||||
plugins: vec![
|
plugins: vec![
|
||||||
external_cjs_modules_plugin.into(),
|
Vc::upcast(external_cjs_modules_plugin),
|
||||||
unsupported_modules_resolve_plugin.into(),
|
Vc::upcast(unsupported_modules_resolve_plugin),
|
||||||
],
|
],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -150,8 +146,8 @@ pub async fn get_server_resolve_options_context(
|
||||||
],
|
],
|
||||||
import_map: Some(next_server_import_map),
|
import_map: Some(next_server_import_map),
|
||||||
plugins: vec![
|
plugins: vec![
|
||||||
server_component_externals_plugin.into(),
|
Vc::upcast(server_component_externals_plugin),
|
||||||
unsupported_modules_resolve_plugin.into(),
|
Vc::upcast(unsupported_modules_resolve_plugin),
|
||||||
],
|
],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -179,8 +175,8 @@ pub async fn get_server_resolve_options_context(
|
||||||
],
|
],
|
||||||
import_map: Some(next_server_import_map),
|
import_map: Some(next_server_import_map),
|
||||||
plugins: vec![
|
plugins: vec![
|
||||||
server_component_externals_plugin.into(),
|
Vc::upcast(server_component_externals_plugin),
|
||||||
unsupported_modules_resolve_plugin.into(),
|
Vc::upcast(unsupported_modules_resolve_plugin),
|
||||||
],
|
],
|
||||||
..Default::default()
|
..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()],
|
custom_conditions: vec![mode.node_env().to_string(), "node".to_string()],
|
||||||
import_map: Some(next_server_import_map),
|
import_map: Some(next_server_import_map),
|
||||||
plugins: vec![
|
plugins: vec![
|
||||||
server_component_externals_plugin.into(),
|
Vc::upcast(server_component_externals_plugin),
|
||||||
unsupported_modules_resolve_plugin.into(),
|
Vc::upcast(unsupported_modules_resolve_plugin),
|
||||||
],
|
],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -222,7 +218,7 @@ pub async fn get_server_resolve_options_context(
|
||||||
enable_node_externals: true,
|
enable_node_externals: true,
|
||||||
module: true,
|
module: true,
|
||||||
custom_conditions: vec![mode.node_env().to_string()],
|
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()
|
..Default::default()
|
||||||
};
|
};
|
||||||
ResolveOptionsContext {
|
ResolveOptionsContext {
|
||||||
|
@ -251,23 +247,23 @@ fn defines(mode: NextMode) -> CompileTimeDefines {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn next_server_defines(mode: NextMode) -> CompileTimeDefinesVc {
|
fn next_server_defines(mode: NextMode) -> Vc<CompileTimeDefines> {
|
||||||
defines(mode).cell()
|
defines(mode).cell()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[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())
|
Ok(free_var_references!(..defines(mode).into_iter()).cell())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn get_server_compile_time_info(
|
pub fn get_server_compile_time_info(
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
process_env: ProcessEnvVc,
|
process_env: Vc<Box<dyn ProcessEnv>>,
|
||||||
server_addr: ServerAddrVc,
|
server_addr: Vc<ServerAddr>,
|
||||||
) -> CompileTimeInfoVc {
|
) -> Vc<CompileTimeInfo> {
|
||||||
CompileTimeInfo::builder(EnvironmentVc::new(Value::new(
|
CompileTimeInfo::builder(Environment::new(Value::new(
|
||||||
ExecutionEnvironment::NodeJsLambda(NodeJsEnvironmentVc::current(process_env, server_addr)),
|
ExecutionEnvironment::NodeJsLambda(NodeJsEnvironment::current(process_env, server_addr)),
|
||||||
)))
|
)))
|
||||||
.defines(next_server_defines(mode))
|
.defines(next_server_defines(mode))
|
||||||
.free_var_references(next_server_free_vars(mode))
|
.free_var_references(next_server_free_vars(mode))
|
||||||
|
@ -276,12 +272,12 @@ pub fn get_server_compile_time_info(
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn get_server_module_options_context(
|
pub async fn get_server_module_options_context(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
execution_context: ExecutionContextVc,
|
execution_context: Vc<ExecutionContext>,
|
||||||
ty: Value<ServerContextType>,
|
ty: Value<ServerContextType>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
) -> Result<ModuleOptionsContextVc> {
|
) -> Result<Vc<ModuleOptionsContext>> {
|
||||||
let custom_rules = get_next_server_transforms_rules(next_config, ty.into_value(), mode).await?;
|
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?;
|
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| {
|
let enable_webpack_loaders = webpack_rules.map(|rules| {
|
||||||
WebpackLoadersOptions {
|
WebpackLoadersOptions {
|
||||||
rules,
|
rules,
|
||||||
loader_runner_package: Some(get_external_next_compiled_package_mapping(
|
loader_runner_package: Some(get_external_next_compiled_package_mapping(Vc::cell(
|
||||||
StringVc::cell("loader-runner".to_owned()),
|
"loader-runner".to_owned(),
|
||||||
)),
|
))),
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
});
|
});
|
||||||
|
@ -308,13 +304,12 @@ pub async fn get_server_module_options_context(
|
||||||
let styled_components_transform_plugin =
|
let styled_components_transform_plugin =
|
||||||
*get_styled_components_transform_plugin(next_config).await?;
|
*get_styled_components_transform_plugin(next_config).await?;
|
||||||
let styled_jsx_transform_plugin = *get_styled_jsx_transform_plugin().await?;
|
let styled_jsx_transform_plugin = *get_styled_jsx_transform_plugin().await?;
|
||||||
let server_directive_transform_plugin = Some(TransformPluginVc::cell(Box::new(
|
let server_directive_transform_plugin =
|
||||||
ServerDirectiveTransformer::new(
|
Some(Vc::cell(Box::new(ServerDirectiveTransformer::new(
|
||||||
// ServerDirective is not implemented yet and always reports an issue.
|
// 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.
|
// 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
|
// ModuleOptionsContext related options
|
||||||
let tsconfig = get_typescript_transform_options(project_path);
|
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 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_swc_ecma_transform_plugin(project_path, next_config).await?,
|
||||||
*get_relay_transform_plugin(next_config).await?,
|
*get_relay_transform_plugin(next_config).await?,
|
||||||
*get_emotion_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 output_transforms = vec![];
|
||||||
|
|
||||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||||
CustomEcmascriptTransformPlugins {
|
CustomEcmascriptTransformPlugins {
|
||||||
source_transforms: source_transforms.clone(),
|
source_transforms: source_transforms.clone(),
|
||||||
output_transforms: output_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() {
|
let module_options_context = match ty.into_value() {
|
||||||
ServerContextType::Pages { .. } | ServerContextType::PagesData { .. } => {
|
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_components_transform_plugin,
|
||||||
styled_jsx_transform_plugin,
|
styled_jsx_transform_plugin,
|
||||||
]
|
]
|
||||||
|
@ -361,7 +356,7 @@ pub async fn get_server_module_options_context(
|
||||||
|
|
||||||
base_source_transforms.extend(source_transforms);
|
base_source_transforms.extend(source_transforms);
|
||||||
|
|
||||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||||
CustomEcmascriptTransformPlugins {
|
CustomEcmascriptTransformPlugins {
|
||||||
source_transforms: base_source_transforms,
|
source_transforms: base_source_transforms,
|
||||||
output_transforms,
|
output_transforms,
|
||||||
|
@ -403,7 +398,7 @@ pub async fn get_server_module_options_context(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ServerContextType::AppSSR { .. } => {
|
ServerContextType::AppSSR { .. } => {
|
||||||
let mut base_source_transforms: Vec<TransformPluginVc> = vec![
|
let mut base_source_transforms: Vec<Vc<TransformPlugin>> = vec![
|
||||||
styled_components_transform_plugin,
|
styled_components_transform_plugin,
|
||||||
styled_jsx_transform_plugin,
|
styled_jsx_transform_plugin,
|
||||||
server_directive_transform_plugin,
|
server_directive_transform_plugin,
|
||||||
|
@ -412,7 +407,7 @@ pub async fn get_server_module_options_context(
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let base_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
let base_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||||
CustomEcmascriptTransformPlugins {
|
CustomEcmascriptTransformPlugins {
|
||||||
source_transforms: base_source_transforms.clone(),
|
source_transforms: base_source_transforms.clone(),
|
||||||
output_transforms: vec![],
|
output_transforms: vec![],
|
||||||
|
@ -421,7 +416,7 @@ pub async fn get_server_module_options_context(
|
||||||
|
|
||||||
base_source_transforms.extend(source_transforms);
|
base_source_transforms.extend(source_transforms);
|
||||||
|
|
||||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||||
CustomEcmascriptTransformPlugins {
|
CustomEcmascriptTransformPlugins {
|
||||||
source_transforms: base_source_transforms,
|
source_transforms: base_source_transforms,
|
||||||
output_transforms,
|
output_transforms,
|
||||||
|
@ -465,7 +460,7 @@ pub async fn get_server_module_options_context(
|
||||||
ecmascript_client_reference_transition_name,
|
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,
|
styled_components_transform_plugin,
|
||||||
server_directive_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) =
|
if let Some(ecmascript_client_reference_transition_name) =
|
||||||
ecmascript_client_reference_transition_name
|
ecmascript_client_reference_transition_name
|
||||||
{
|
{
|
||||||
base_source_transforms.push(TransformPluginVc::cell(Box::new(
|
base_source_transforms.push(Vc::cell(Box::new(ClientDirectiveTransformer::new(
|
||||||
ClientDirectiveTransformer::new(ecmascript_client_reference_transition_name),
|
ecmascript_client_reference_transition_name,
|
||||||
)));
|
)) as _));
|
||||||
}
|
}
|
||||||
|
|
||||||
let base_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
let base_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||||
CustomEcmascriptTransformPlugins {
|
CustomEcmascriptTransformPlugins {
|
||||||
source_transforms: base_source_transforms.clone(),
|
source_transforms: base_source_transforms.clone(),
|
||||||
output_transforms: vec![],
|
output_transforms: vec![],
|
||||||
|
@ -490,7 +485,7 @@ pub async fn get_server_module_options_context(
|
||||||
|
|
||||||
base_source_transforms.extend(source_transforms);
|
base_source_transforms.extend(source_transforms);
|
||||||
|
|
||||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||||
CustomEcmascriptTransformPlugins {
|
CustomEcmascriptTransformPlugins {
|
||||||
source_transforms: base_source_transforms,
|
source_transforms: base_source_transforms,
|
||||||
output_transforms,
|
output_transforms,
|
||||||
|
@ -561,7 +556,7 @@ pub async fn get_server_module_options_context(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ServerContextType::Middleware => {
|
ServerContextType::Middleware => {
|
||||||
let mut base_source_transforms: Vec<TransformPluginVc> = vec![
|
let mut base_source_transforms: Vec<Vc<TransformPlugin>> = vec![
|
||||||
styled_components_transform_plugin,
|
styled_components_transform_plugin,
|
||||||
styled_jsx_transform_plugin,
|
styled_jsx_transform_plugin,
|
||||||
]
|
]
|
||||||
|
@ -571,7 +566,7 @@ pub async fn get_server_module_options_context(
|
||||||
|
|
||||||
base_source_transforms.extend(source_transforms);
|
base_source_transforms.extend(source_transforms);
|
||||||
|
|
||||||
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell(
|
let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell(
|
||||||
CustomEcmascriptTransformPlugins {
|
CustomEcmascriptTransformPlugins {
|
||||||
source_transforms: base_source_transforms,
|
source_transforms: base_source_transforms,
|
||||||
output_transforms,
|
output_transforms,
|
||||||
|
@ -616,7 +611,7 @@ pub async fn get_server_module_options_context(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn get_build_module_options_context() -> ModuleOptionsContextVc {
|
pub fn get_build_module_options_context() -> Vc<ModuleOptionsContext> {
|
||||||
ModuleOptionsContext {
|
ModuleOptionsContext {
|
||||||
enable_typescript_transform: Some(Default::default()),
|
enable_typescript_transform: Some(Default::default()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -626,15 +621,16 @@ pub fn get_build_module_options_context() -> ModuleOptionsContextVc {
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn get_server_runtime_entries(
|
pub fn get_server_runtime_entries(
|
||||||
project_root: FileSystemPathVc,
|
project_root: Vc<FileSystemPath>,
|
||||||
env: ProcessEnvVc,
|
env: Vc<Box<dyn ProcessEnv>>,
|
||||||
ty: Value<ServerContextType>,
|
ty: Value<ServerContextType>,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
) -> RuntimeEntriesVc {
|
) -> Vc<RuntimeEntries> {
|
||||||
let mut runtime_entries = vec![RuntimeEntry::Source(
|
let mut runtime_entries = vec![RuntimeEntry::Source(Vc::upcast(ProcessEnvAsset::new(
|
||||||
ProcessEnvAssetVc::new(project_root, env_for_js(env, false, next_config)).into(),
|
project_root,
|
||||||
)
|
env_for_js(env, false, next_config),
|
||||||
|
)))
|
||||||
.cell()];
|
.cell()];
|
||||||
|
|
||||||
match mode {
|
match mode {
|
||||||
|
@ -643,10 +639,10 @@ pub fn get_server_runtime_entries(
|
||||||
if let ServerContextType::AppRSC { .. } = ty.into_value() {
|
if let ServerContextType::AppRSC { .. } = ty.into_value() {
|
||||||
runtime_entries.push(
|
runtime_entries.push(
|
||||||
RuntimeEntry::Request(
|
RuntimeEntry::Request(
|
||||||
RequestVc::parse(Value::new(Pattern::Constant(
|
Request::parse(Value::new(Pattern::Constant(
|
||||||
"./build/server/app-bootstrap.ts".to_string(),
|
"./build/server/app-bootstrap.ts".to_string(),
|
||||||
))),
|
))),
|
||||||
next_js_fs().root().join("_"),
|
next_js_fs().root().join("_".to_string()),
|
||||||
)
|
)
|
||||||
.cell(),
|
.cell(),
|
||||||
);
|
);
|
||||||
|
@ -654,26 +650,26 @@ pub fn get_server_runtime_entries(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeEntriesVc::cell(runtime_entries)
|
Vc::cell(runtime_entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn get_server_chunking_context(
|
pub fn get_server_chunking_context(
|
||||||
project_path: FileSystemPathVc,
|
project_path: Vc<FileSystemPath>,
|
||||||
node_root: FileSystemPathVc,
|
node_root: Vc<FileSystemPath>,
|
||||||
// TODO(alexkirsz) Is this even necessary? Are assets not always on the client chunking context
|
// TODO(alexkirsz) Is this even necessary? Are assets not always on the client chunking context
|
||||||
// anyway?
|
// anyway?
|
||||||
client_root: FileSystemPathVc,
|
client_root: Vc<FileSystemPath>,
|
||||||
environment: EnvironmentVc,
|
environment: Vc<Environment>,
|
||||||
) -> BuildChunkingContextVc {
|
) -> Vc<BuildChunkingContext> {
|
||||||
// TODO(alexkirsz) This should return a trait that can be implemented by the
|
// TODO(alexkirsz) This should return a trait that can be implemented by the
|
||||||
// different server chunking contexts. OR the build chunking context should
|
// different server chunking contexts. OR the build chunking context should
|
||||||
// support both production and development modes.
|
// support both production and development modes.
|
||||||
BuildChunkingContextVc::builder(
|
BuildChunkingContext::builder(
|
||||||
project_path,
|
project_path,
|
||||||
node_root,
|
node_root,
|
||||||
node_root.join("server/chunks"),
|
node_root.join("server/chunks".to_string()),
|
||||||
client_root.join("static/media"),
|
client_root.join("static/media".to_string()),
|
||||||
environment,
|
environment,
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use turbo_tasks::primitives::{BoolVc, StringsVc};
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::{glob::GlobVc, FileJsonContent, FileSystemPathVc},
|
turbo::tasks_fs::{glob::Glob, FileJsonContent, FileSystemPath},
|
||||||
turbopack::core::{
|
turbopack::core::{
|
||||||
asset::Asset,
|
asset::Asset,
|
||||||
resolve::{
|
resolve::{
|
||||||
find_context_file,
|
find_context_file,
|
||||||
node::node_cjs_resolve_options,
|
node::node_cjs_resolve_options,
|
||||||
package_json,
|
package_json,
|
||||||
parse::{Request, RequestVc},
|
parse::Request,
|
||||||
plugin::{ResolvePlugin, ResolvePluginConditionVc, ResolvePluginVc},
|
plugin::{ResolvePlugin, ResolvePluginCondition},
|
||||||
resolve, FindContextFileResult, PrimaryResolveResult, ResolveResult,
|
resolve, FindContextFileResult, PrimaryResolveResult, ResolveResult,
|
||||||
ResolveResultOptionVc,
|
ResolveResultOption,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -23,9 +23,9 @@ use turbopack_binding::{
|
||||||
#[turbo_tasks::value(into = "shared")]
|
#[turbo_tasks::value(into = "shared")]
|
||||||
pub enum ExternalPredicate {
|
pub enum ExternalPredicate {
|
||||||
/// Mark all modules as external if they're not listed in the list.
|
/// 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 mark modules listed as external.
|
||||||
Only(StringsVc),
|
Only(Vc<Vec<String>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark modules as external, so they're resolved at runtime instead of bundled.
|
/// 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.
|
/// possible to resolve them at runtime.
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub(crate) struct ExternalCjsModulesResolvePlugin {
|
pub(crate) struct ExternalCjsModulesResolvePlugin {
|
||||||
root: FileSystemPathVc,
|
root: Vc<FileSystemPath>,
|
||||||
predicate: ExternalPredicateVc,
|
predicate: Vc<ExternalPredicate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ExternalCjsModulesResolvePluginVc {
|
impl ExternalCjsModulesResolvePlugin {
|
||||||
#[turbo_tasks::function]
|
#[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()
|
ExternalCjsModulesResolvePlugin { root, predicate }.cell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn is_node_resolveable(
|
async fn is_node_resolveable(
|
||||||
context: FileSystemPathVc,
|
context: Vc<FileSystemPath>,
|
||||||
request: RequestVc,
|
request: Vc<Request>,
|
||||||
expected: FileSystemPathVc,
|
expected: Vc<FileSystemPath>,
|
||||||
) -> Result<BoolVc> {
|
) -> Result<Vc<bool>> {
|
||||||
let node_resolve_result = resolve(context, request, node_cjs_resolve_options(context.root()));
|
let node_resolve_result = resolve(context, request, node_cjs_resolve_options(context.root()));
|
||||||
let primary_node_assets = node_resolve_result.primary_assets().await?;
|
let primary_node_assets = node_resolve_result.primary_assets().await?;
|
||||||
let Some(node_asset) = primary_node_assets.first() else {
|
let Some(node_asset) = primary_node_assets.first() else {
|
||||||
// can't resolve request with node.js options
|
// 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? {
|
if node_asset.ident().path().resolve().await? != expected.resolve().await? {
|
||||||
// node.js resolves to a different file
|
// 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());
|
static PNPM: Lazy<Regex> = Lazy::new(|| Regex::new(r"(?:/|^)node_modules/(.pnpm/.+)").unwrap());
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn condition(root: FileSystemPathVc) -> ResolvePluginConditionVc {
|
fn condition(root: Vc<FileSystemPath>) -> Vc<ResolvePluginCondition> {
|
||||||
ResolvePluginConditionVc::new(root.root(), GlobVc::new("**/node_modules/**"))
|
ResolvePluginCondition::new(root.root(), Glob::new("**/node_modules/**".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
|
impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn after_resolve_condition(&self) -> ResolvePluginConditionVc {
|
fn after_resolve_condition(&self) -> Vc<ResolvePluginCondition> {
|
||||||
condition(self.root)
|
condition(self.root)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn after_resolve(
|
async fn after_resolve(
|
||||||
&self,
|
&self,
|
||||||
fs_path: FileSystemPathVc,
|
fs_path: Vc<FileSystemPath>,
|
||||||
context: FileSystemPathVc,
|
context: Vc<FileSystemPath>,
|
||||||
request: RequestVc,
|
request: Vc<Request>,
|
||||||
) -> Result<ResolveResultOptionVc> {
|
) -> Result<Vc<ResolveResultOption>> {
|
||||||
if *condition(self.root).matches(context).await? {
|
if *condition(self.root).matches(context).await? {
|
||||||
return Ok(ResolveResultOptionVc::none());
|
return Ok(ResolveResultOption::none());
|
||||||
}
|
}
|
||||||
if !matches!(&*request.await?, Request::Module { .. }) {
|
if !matches!(&*request.await?, Request::Module { .. }) {
|
||||||
return Ok(ResolveResultOptionVc::none());
|
return Ok(ResolveResultOption::none());
|
||||||
}
|
}
|
||||||
|
|
||||||
let raw_fs_path = &*fs_path.await?;
|
let raw_fs_path = &*fs_path.await?;
|
||||||
|
@ -103,14 +103,14 @@ impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
|
||||||
let exception_glob = packages_glob(*exceptions).await?;
|
let exception_glob = packages_glob(*exceptions).await?;
|
||||||
|
|
||||||
if exception_glob.execute(&raw_fs_path.path) {
|
if exception_glob.execute(&raw_fs_path.path) {
|
||||||
return Ok(ResolveResultOptionVc::none());
|
return Ok(ResolveResultOption::none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExternalPredicate::Only(externals) => {
|
ExternalPredicate::Only(externals) => {
|
||||||
let external_glob = packages_glob(*externals).await?;
|
let external_glob = packages_glob(*externals).await?;
|
||||||
|
|
||||||
if !external_glob.execute(&raw_fs_path.path) {
|
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
|
// node.js only supports these file extensions
|
||||||
// mjs is an esm module and we can't bundle that yet
|
// mjs is an esm module and we can't bundle that yet
|
||||||
if !matches!(
|
if !matches!(
|
||||||
raw_fs_path.extension(),
|
raw_fs_path.extension_ref(),
|
||||||
Some("cjs" | "js" | "node" | "json")
|
Some("cjs" | "js" | "node" | "json")
|
||||||
) {
|
) {
|
||||||
return Ok(ResolveResultOptionVc::none());
|
return Ok(ResolveResultOption::none());
|
||||||
}
|
}
|
||||||
|
|
||||||
let FindContextFileResult::Found(package_json, _) =
|
let FindContextFileResult::Found(package_json, _) =
|
||||||
*find_context_file(fs_path.parent(), package_json()).await?
|
*find_context_file(fs_path.parent(), package_json()).await?
|
||||||
else {
|
else {
|
||||||
// can't find package.json
|
// can't find package.json
|
||||||
return Ok(ResolveResultOptionVc::none());
|
return Ok(ResolveResultOption::none());
|
||||||
};
|
};
|
||||||
let FileJsonContent::Content(package) = &*package_json.read_json().await? else {
|
let FileJsonContent::Content(package) = &*package_json.read_json().await? else {
|
||||||
// can't parse package.json
|
// can't parse package.json
|
||||||
return Ok(ResolveResultOptionVc::none());
|
return Ok(ResolveResultOption::none());
|
||||||
};
|
};
|
||||||
|
|
||||||
// always bundle esm modules
|
// always bundle esm modules
|
||||||
if let Some("module") = package["type"].as_str() {
|
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
|
// check if we can resolve the package from the project dir with node.js resolve
|
||||||
// options (might be hidden by pnpm)
|
// options (might be hidden by pnpm)
|
||||||
if *is_node_resolveable(self.root.root(), request, fs_path).await? {
|
if *is_node_resolveable(self.root.root(), request, fs_path).await? {
|
||||||
// mark as external
|
// mark as external
|
||||||
return Ok(ResolveResultOptionVc::some(
|
return Ok(ResolveResultOption::some(
|
||||||
ResolveResult::primary(PrimaryResolveResult::OriginalReferenceExternal).cell(),
|
ResolveResult::primary(PrimaryResolveResult::OriginalReferenceExternal).cell(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
|
||||||
// options, to come here like the `module` field in package.json
|
// options, to come here like the `module` field in package.json
|
||||||
if *is_node_resolveable(context, request, fs_path).await? {
|
if *is_node_resolveable(context, request, fs_path).await? {
|
||||||
// mark as external
|
// mark as external
|
||||||
return Ok(ResolveResultOptionVc::some(
|
return Ok(ResolveResultOption::some(
|
||||||
ResolveResult::primary(
|
ResolveResult::primary(
|
||||||
PrimaryResolveResult::OriginalReferenceTypeExternal(
|
PrimaryResolveResult::OriginalReferenceTypeExternal(
|
||||||
import_path.as_str().to_string(),
|
import_path.as_str().to_string(),
|
||||||
|
@ -172,13 +172,13 @@ impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(ResolveResultOptionVc::none())
|
Ok(ResolveResultOption::none())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn packages_glob(packages: StringsVc) -> Result<GlobVc> {
|
async fn packages_glob(packages: Vc<Vec<String>>) -> Result<Vc<Glob>> {
|
||||||
Ok(GlobVc::new(&format!(
|
Ok(Glob::new(format!(
|
||||||
"**/node_modules/{{{}}}/**",
|
"**/node_modules/{{{}}}/**",
|
||||||
packages.await?.join(",")
|
packages.await?.join(",")
|
||||||
)))
|
)))
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use next_transform_strip_page_exports::ExportFilter;
|
use next_transform_strip_page_exports::ExportFilter;
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::turbopack::turbopack::module_options::ModuleRule;
|
use turbopack_binding::turbopack::turbopack::module_options::ModuleRule;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
next_client_reference::css_client_reference::css_client_reference_rule::get_next_css_client_reference_transforms_rule,
|
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_server::context::ServerContextType,
|
||||||
next_shared::transforms::{
|
next_shared::transforms::{
|
||||||
get_next_dynamic_transform_rule, get_next_font_transform_rule, get_next_image_rule,
|
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
|
/// Returns a list of module rules which apply server-side, Next.js-specific
|
||||||
/// transforms.
|
/// transforms.
|
||||||
pub async fn get_next_server_transforms_rules(
|
pub async fn get_next_server_transforms_rules(
|
||||||
next_config: NextConfigVc,
|
next_config: Vc<NextConfig>,
|
||||||
context_ty: ServerContextType,
|
context_ty: ServerContextType,
|
||||||
mode: NextMode,
|
mode: NextMode,
|
||||||
) -> Result<Vec<ModuleRule>> {
|
) -> Result<Vec<ModuleRule>> {
|
||||||
|
|
|
@ -2,4 +2,4 @@ pub(crate) mod server_component_module;
|
||||||
pub(crate) mod server_component_reference;
|
pub(crate) mod server_component_reference;
|
||||||
pub(crate) mod server_component_transition;
|
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 anyhow::{bail, Result};
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
use turbo_tasks::{primitives::StringVc, Value};
|
use turbo_tasks::{Value, Vc};
|
||||||
use turbo_tasks_fs::FileSystemPathVc;
|
use turbo_tasks_fs::FileSystemPath;
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetContentVc, AssetVc},
|
asset::{Asset, AssetContent},
|
||||||
chunk::{
|
chunk::{
|
||||||
availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableModule,
|
availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableModule, ChunkingContext,
|
||||||
ChunkableModuleVc, ChunkingContextVc,
|
|
||||||
},
|
},
|
||||||
ident::AssetIdentVc,
|
ident::AssetIdent,
|
||||||
module::{Module, ModuleVc},
|
module::Module,
|
||||||
reference::{AssetReferenceVc, AssetReferencesVc},
|
reference::{AssetReference, AssetReferences},
|
||||||
},
|
},
|
||||||
|
ecmascript::chunk::EcmascriptChunkItemExt,
|
||||||
turbopack::ecmascript::{
|
turbopack::ecmascript::{
|
||||||
chunk::{
|
chunk::{
|
||||||
EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc,
|
EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkItemContent,
|
||||||
EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc,
|
EcmascriptChunkPlaceable, EcmascriptChunkingContext, EcmascriptExports,
|
||||||
EcmascriptChunkVc, EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc,
|
|
||||||
},
|
},
|
||||||
utils::StringifyJs,
|
utils::StringifyJs,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::server_component_reference::NextServerComponentModuleReferenceVc;
|
use super::server_component_reference::NextServerComponentModuleReference;
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn modifier() -> StringVc {
|
fn modifier() -> Vc<String> {
|
||||||
StringVc::cell("Next.js server component".to_string())
|
Vc::cell("Next.js server component".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(shared)]
|
#[turbo_tasks::value(shared)]
|
||||||
pub struct NextServerComponentModule {
|
pub struct NextServerComponentModule {
|
||||||
module: EcmascriptChunkPlaceableVc,
|
module: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextServerComponentModuleVc {
|
impl NextServerComponentModule {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(module: EcmascriptChunkPlaceableVc) -> Self {
|
pub fn new(module: Vc<Box<dyn EcmascriptChunkPlaceable>>) -> Vc<Self> {
|
||||||
NextServerComponentModule { module }.cell()
|
NextServerComponentModule { module }.cell()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn server_path(self_vc: NextServerComponentModuleVc) -> Result<FileSystemPathVc> {
|
pub async fn server_path(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
|
||||||
let this = self_vc.await?;
|
let this = self.await?;
|
||||||
Ok(this.module.ident().path())
|
Ok(this.module.ident().path())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,20 +51,21 @@ impl NextServerComponentModuleVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Asset for NextServerComponentModule {
|
impl Asset for NextServerComponentModule {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn ident(&self) -> AssetIdentVc {
|
fn ident(&self) -> Vc<AssetIdent> {
|
||||||
self.module.ident().with_modifier(modifier())
|
self.module.ident().with_modifier(modifier())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn content(&self) -> Result<AssetContentVc> {
|
fn content(&self) -> Result<Vc<AssetContent>> {
|
||||||
bail!("Next.js server component module has no content")
|
bail!("Next.js server component module has no content")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn references(&self) -> AssetReferencesVc {
|
fn references(&self) -> Vc<AssetReferences> {
|
||||||
let references: Vec<AssetReferenceVc> =
|
let references: Vec<Vc<Box<dyn AssetReference>>> = vec![Vc::upcast(
|
||||||
vec![NextServerComponentModuleReferenceVc::new(self.module.into()).into()];
|
NextServerComponentModuleReference::new(Vc::upcast(self.module)),
|
||||||
AssetReferencesVc::cell(references)
|
)];
|
||||||
|
Vc::cell(references)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,16 +76,15 @@ impl Module for NextServerComponentModule {}
|
||||||
impl ChunkableModule for NextServerComponentModule {
|
impl ChunkableModule for NextServerComponentModule {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn as_chunk(
|
fn as_chunk(
|
||||||
self_vc: NextServerComponentModuleVc,
|
self: Vc<Self>,
|
||||||
context: ChunkingContextVc,
|
context: Vc<Box<dyn ChunkingContext>>,
|
||||||
availability_info: Value<AvailabilityInfo>,
|
availability_info: Value<AvailabilityInfo>,
|
||||||
) -> ChunkVc {
|
) -> Vc<Box<dyn Chunk>> {
|
||||||
EcmascriptChunkVc::new(
|
Vc::upcast(EcmascriptChunk::new(
|
||||||
context,
|
context,
|
||||||
self_vc.as_ecmascript_chunk_placeable(),
|
Vc::upcast(self),
|
||||||
availability_info,
|
availability_info,
|
||||||
)
|
))
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,19 +92,20 @@ impl ChunkableModule for NextServerComponentModule {
|
||||||
impl EcmascriptChunkPlaceable for NextServerComponentModule {
|
impl EcmascriptChunkPlaceable for NextServerComponentModule {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn as_chunk_item(
|
async fn as_chunk_item(
|
||||||
self_vc: NextServerComponentModuleVc,
|
self: Vc<Self>,
|
||||||
context: EcmascriptChunkingContextVc,
|
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
) -> Result<EcmascriptChunkItemVc> {
|
) -> Result<Vc<Box<dyn EcmascriptChunkItem>>> {
|
||||||
Ok(BuildServerComponentChunkItem {
|
Ok(Vc::upcast(
|
||||||
context,
|
BuildServerComponentChunkItem {
|
||||||
inner: self_vc,
|
context,
|
||||||
}
|
inner: self,
|
||||||
.cell()
|
}
|
||||||
.into())
|
.cell(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn get_exports(&self) -> EcmascriptExportsVc {
|
fn get_exports(&self) -> Vc<EcmascriptExports> {
|
||||||
// TODO This should be EsmExports
|
// TODO This should be EsmExports
|
||||||
EcmascriptExports::Value.cell()
|
EcmascriptExports::Value.cell()
|
||||||
}
|
}
|
||||||
|
@ -113,22 +113,20 @@ impl EcmascriptChunkPlaceable for NextServerComponentModule {
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct BuildServerComponentChunkItem {
|
struct BuildServerComponentChunkItem {
|
||||||
context: EcmascriptChunkingContextVc,
|
context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
inner: NextServerComponentModuleVc,
|
inner: Vc<NextServerComponentModule>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl EcmascriptChunkItem for BuildServerComponentChunkItem {
|
impl EcmascriptChunkItem for BuildServerComponentChunkItem {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn chunking_context(&self) -> EcmascriptChunkingContextVc {
|
fn chunking_context(&self) -> Vc<Box<dyn EcmascriptChunkingContext>> {
|
||||||
self.context
|
self.context
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn content(
|
async fn content(self: Vc<Self>) -> Result<Vc<EcmascriptChunkItemContent>> {
|
||||||
self_vc: BuildServerComponentChunkItemVc,
|
let this = self.await?;
|
||||||
) -> Result<EcmascriptChunkItemContentVc> {
|
|
||||||
let this = self_vc.await?;
|
|
||||||
let inner = this.inner.await?;
|
let inner = this.inner.await?;
|
||||||
|
|
||||||
let module_id = inner.module.as_chunk_item(this.context).id().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]
|
#[turbo_tasks::value_impl]
|
||||||
impl ChunkItem for BuildServerComponentChunkItem {
|
impl ChunkItem for BuildServerComponentChunkItem {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn asset_ident(&self) -> AssetIdentVc {
|
fn asset_ident(&self) -> Vc<AssetIdent> {
|
||||||
self.inner.ident()
|
self.inner.ident()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn references(&self) -> AssetReferencesVc {
|
fn references(&self) -> Vc<AssetReferences> {
|
||||||
self.inner.references()
|
self.inner.references()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc};
|
use turbo_tasks::{ValueToString, Vc};
|
||||||
use turbopack_binding::turbopack::core::{
|
use turbopack_binding::turbopack::core::{
|
||||||
asset::{Asset, AssetVc},
|
asset::Asset,
|
||||||
chunk::{
|
chunk::{ChunkableModuleReference, ChunkingType, ChunkingTypeOption},
|
||||||
ChunkableModuleReference, ChunkableModuleReferenceVc, ChunkingType, ChunkingTypeOptionVc,
|
reference::AssetReference,
|
||||||
},
|
resolve::ResolveResult,
|
||||||
reference::{AssetReference, AssetReferenceVc},
|
|
||||||
resolve::{ResolveResult, ResolveResultVc},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub struct NextServerComponentModuleReference {
|
pub struct NextServerComponentModuleReference {
|
||||||
asset: AssetVc,
|
asset: Vc<Box<dyn Asset>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextServerComponentModuleReferenceVc {
|
impl NextServerComponentModuleReference {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(asset: AssetVc) -> Self {
|
pub fn new(asset: Vc<Box<dyn Asset>>) -> Vc<Self> {
|
||||||
NextServerComponentModuleReference { asset }.cell()
|
NextServerComponentModuleReference { asset }.cell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,8 +23,8 @@ impl NextServerComponentModuleReferenceVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ValueToString for NextServerComponentModuleReference {
|
impl ValueToString for NextServerComponentModuleReference {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn to_string(&self) -> Result<StringVc> {
|
async fn to_string(&self) -> Result<Vc<String>> {
|
||||||
Ok(StringVc::cell(format!(
|
Ok(Vc::cell(format!(
|
||||||
"Next.js server component {}",
|
"Next.js server component {}",
|
||||||
self.asset.ident().to_string().await?
|
self.asset.ident().to_string().await?
|
||||||
)))
|
)))
|
||||||
|
@ -36,7 +34,7 @@ impl ValueToString for NextServerComponentModuleReference {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl AssetReference for NextServerComponentModuleReference {
|
impl AssetReference for NextServerComponentModuleReference {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn resolve_reference(&self) -> ResolveResultVc {
|
fn resolve_reference(&self) -> Vc<ResolveResult> {
|
||||||
ResolveResult::asset(self.asset).cell()
|
ResolveResult::asset(self.asset).cell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,9 +42,9 @@ impl AssetReference for NextServerComponentModuleReference {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ChunkableModuleReference for NextServerComponentModuleReference {
|
impl ChunkableModuleReference for NextServerComponentModuleReference {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn chunking_type(&self) -> ChunkingTypeOptionVc {
|
fn chunking_type(&self) -> Vc<ChunkingTypeOption> {
|
||||||
// TODO(alexkirsz) Instead of isolated parallel, have the server component
|
// TODO(alexkirsz) Instead of isolated parallel, have the server component
|
||||||
// reference create a new chunk group entirely?
|
// 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 anyhow::{bail, Result};
|
||||||
|
use turbo_tasks::Vc;
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
core::module::ModuleVc,
|
core::module::Module,
|
||||||
ecmascript::chunk::EcmascriptChunkPlaceableVc,
|
ecmascript::chunk::EcmascriptChunkPlaceable,
|
||||||
turbopack::{
|
turbopack::{transition::Transition, ModuleAssetContext},
|
||||||
transition::{Transition, TransitionVc},
|
|
||||||
ModuleAssetContextVc,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::server_component_module::NextServerComponentModuleVc;
|
use super::server_component_module::NextServerComponentModule;
|
||||||
|
|
||||||
/// This transition wraps a module into a marker
|
/// This transition wraps a module into a marker
|
||||||
/// [`NextServerComponentModuleVc`].
|
/// [`Vc<NextServerComponentModule>`].
|
||||||
///
|
///
|
||||||
/// When walking the module graph to build the client reference manifest, this
|
/// When walking the module graph to build the client reference manifest, this
|
||||||
/// is used to determine under which server component CSS client references are
|
/// 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 {}
|
pub struct NextServerComponentTransition {}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl NextServerComponentTransitionVc {
|
impl NextServerComponentTransition {
|
||||||
/// Creates a new [`NextServerComponentTransitionVc`].
|
/// Creates a new [`Vc<NextServerComponentTransition>`].
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Vc<Self> {
|
||||||
NextServerComponentTransition {}.cell()
|
NextServerComponentTransition {}.cell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,14 +30,16 @@ impl NextServerComponentTransitionVc {
|
||||||
impl Transition for NextServerComponentTransition {
|
impl Transition for NextServerComponentTransition {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn process_module(
|
async fn process_module(
|
||||||
_self_vc: NextServerComponentTransitionVc,
|
self: Vc<Self>,
|
||||||
module: ModuleVc,
|
module: Vc<Box<dyn Module>>,
|
||||||
_context: ModuleAssetContextVc,
|
_context: Vc<ModuleAssetContext>,
|
||||||
) -> Result<ModuleVc> {
|
) -> Result<Vc<Box<dyn Module>>> {
|
||||||
let Some(module) = EcmascriptChunkPlaceableVc::resolve_from(module).await? else {
|
let Some(module) =
|
||||||
|
Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(module).await?
|
||||||
|
else {
|
||||||
bail!("not an ecmascript module");
|
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 anyhow::Result;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use turbo_tasks_fs::glob::GlobVc;
|
use turbo_tasks::Vc;
|
||||||
|
use turbo_tasks_fs::glob::Glob;
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::FileSystemPathVc,
|
turbo::tasks_fs::FileSystemPath,
|
||||||
turbopack::core::{
|
turbopack::core::{
|
||||||
issue::unsupported_module::UnsupportedModuleIssue,
|
issue::{unsupported_module::UnsupportedModuleIssue, IssueExt},
|
||||||
resolve::{
|
resolve::{
|
||||||
parse::{Request, RequestVc},
|
parse::Request,
|
||||||
pattern::Pattern,
|
pattern::Pattern,
|
||||||
plugin::{ResolvePlugin, ResolvePluginConditionVc, ResolvePluginVc},
|
plugin::{ResolvePlugin, ResolvePluginCondition},
|
||||||
ResolveResultOptionVc,
|
ResolveResultOption,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -23,13 +24,13 @@ lazy_static! {
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub(crate) struct UnsupportedModulesResolvePlugin {
|
pub(crate) struct UnsupportedModulesResolvePlugin {
|
||||||
root: FileSystemPathVc,
|
root: Vc<FileSystemPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl UnsupportedModulesResolvePluginVc {
|
impl UnsupportedModulesResolvePlugin {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub fn new(root: FileSystemPathVc) -> Self {
|
pub fn new(root: Vc<FileSystemPath>) -> Vc<Self> {
|
||||||
UnsupportedModulesResolvePlugin { root }.cell()
|
UnsupportedModulesResolvePlugin { root }.cell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,17 +38,17 @@ impl UnsupportedModulesResolvePluginVc {
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ResolvePlugin for UnsupportedModulesResolvePlugin {
|
impl ResolvePlugin for UnsupportedModulesResolvePlugin {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn after_resolve_condition(&self) -> ResolvePluginConditionVc {
|
fn after_resolve_condition(&self) -> Vc<ResolvePluginCondition> {
|
||||||
ResolvePluginConditionVc::new(self.root.root(), GlobVc::new("**"))
|
ResolvePluginCondition::new(self.root.root(), Glob::new("**".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn after_resolve(
|
async fn after_resolve(
|
||||||
&self,
|
&self,
|
||||||
_fs_path: FileSystemPathVc,
|
_fs_path: Vc<FileSystemPath>,
|
||||||
context: FileSystemPathVc,
|
context: Vc<FileSystemPath>,
|
||||||
request: RequestVc,
|
request: Vc<Request>,
|
||||||
) -> Result<ResolveResultOptionVc> {
|
) -> Result<Vc<ResolveResultOption>> {
|
||||||
if let Request::Module {
|
if let Request::Module {
|
||||||
module,
|
module,
|
||||||
path,
|
path,
|
||||||
|
@ -62,7 +63,6 @@ impl ResolvePlugin for UnsupportedModulesResolvePlugin {
|
||||||
package_path: None,
|
package_path: None,
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
.as_issue()
|
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,12 +74,11 @@ impl ResolvePlugin for UnsupportedModulesResolvePlugin {
|
||||||
package_path: Some(path.to_owned()),
|
package_path: Some(path.to_owned()),
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
.as_issue()
|
|
||||||
.emit();
|
.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