From 3c0322828ef402c46389578f3171ae2664d23e25 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 13 Jul 2023 14:38:35 +0200 Subject: [PATCH 1/9] Experimental Next.rs API Co-authored-by: Tobias Koppers Co-authored-by: Justin Ridgewell --- Cargo.lock | 18 + Cargo.toml | 2 + packages/next-swc/crates/napi/Cargo.toml | 1 + packages/next-swc/crates/napi/src/lib.rs | 2 + .../crates/napi/src/next_api/endpoint.rs | 55 ++ .../next-swc/crates/napi/src/next_api/mod.rs | 3 + .../crates/napi/src/next_api/project.rs | 195 +++++++ .../crates/napi/src/next_api/utils.rs | 135 +++++ packages/next-swc/crates/next-api/Cargo.toml | 46 ++ packages/next-swc/crates/next-api/build.rs | 5 + packages/next-swc/crates/next-api/src/app.rs | 67 +++ packages/next-swc/crates/next-api/src/lib.rs | 13 + .../next-swc/crates/next-api/src/pages.rs | 361 ++++++++++++ .../next-swc/crates/next-api/src/project.rs | 517 ++++++++++++++++++ .../next-swc/crates/next-api/src/route.rs | 43 ++ .../next-build/src/next_pages/page_entries.rs | 6 +- .../next-core/js/src/entry/config/next.js | 9 +- .../crates/next-core/src/app_structure.rs | 19 +- .../next-swc/crates/next-core/src/emit.rs | 89 +++ packages/next-swc/crates/next-core/src/lib.rs | 4 +- .../next-swc/crates/next-core/src/manifest.rs | 6 +- .../crates/next-core/src/next_config.rs | 98 +++- .../crates/next-core/src/pages_structure.rs | 6 +- packages/next-swc/crates/next-dev/src/lib.rs | 11 +- packages/next/src/build/index.ts | 2 +- packages/next/src/build/swc/index.ts | 423 +++++++++++++- .../plugins/next-trace-entrypoints-plugin.ts | 6 +- packages/next/src/cli/next-dev.ts | 61 ++- packages/next/src/server/config-shared.ts | 4 +- packages/next/src/server/lib/start-server.ts | 1 - 30 files changed, 2144 insertions(+), 64 deletions(-) create mode 100644 packages/next-swc/crates/napi/src/next_api/endpoint.rs create mode 100644 packages/next-swc/crates/napi/src/next_api/mod.rs create mode 100644 packages/next-swc/crates/napi/src/next_api/project.rs create mode 100644 packages/next-swc/crates/napi/src/next_api/utils.rs create mode 100644 packages/next-swc/crates/next-api/Cargo.toml create mode 100644 packages/next-swc/crates/next-api/build.rs create mode 100644 packages/next-swc/crates/next-api/src/app.rs create mode 100644 packages/next-swc/crates/next-api/src/lib.rs create mode 100644 packages/next-swc/crates/next-api/src/pages.rs create mode 100644 packages/next-swc/crates/next-api/src/project.rs create mode 100644 packages/next-swc/crates/next-api/src/route.rs create mode 100644 packages/next-swc/crates/next-core/src/emit.rs diff --git a/Cargo.lock b/Cargo.lock index 2954ce852af6a..f129441260848 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3367,6 +3367,23 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "next-api" +version = "0.1.0" +dependencies = [ + "anyhow", + "futures", + "indexmap", + "next-core", + "once_cell", + "serde", + "tokio", + "tracing", + "tracing-subscriber", + "turbo-tasks", + "turbopack-binding", +] + [[package]] name = "next-build" version = "0.1.0" @@ -3519,6 +3536,7 @@ dependencies = [ "napi", "napi-build", "napi-derive", + "next-api", "next-build", "next-core", "next-dev", diff --git a/Cargo.toml b/Cargo.toml index 30e394749f8b8..ca53f1481e2b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "packages/next-swc/crates/core", "packages/next-swc/crates/napi", "packages/next-swc/crates/wasm", + "packages/next-swc/crates/next-api", "packages/next-swc/crates/next-build", "packages/next-swc/crates/next-core", "packages/next-swc/crates/next-dev", @@ -26,6 +27,7 @@ lto = true [workspace.dependencies] # Workspace crates +next-api = { path = "packages/next-swc/crates/next-api", default-features = false } next-build = { path = "packages/next-swc/crates/next-build", default-features = false } next-core = { path = "packages/next-swc/crates/next-core", default-features = false } next-dev = { path = "packages/next-swc/crates/next-dev", default-features = false, features = [ diff --git a/packages/next-swc/crates/napi/Cargo.toml b/packages/next-swc/crates/napi/Cargo.toml index 922fdd46cb44d..9c47caf113e79 100644 --- a/packages/next-swc/crates/napi/Cargo.toml +++ b/packages/next-swc/crates/napi/Cargo.toml @@ -43,6 +43,7 @@ napi = { version = "2", default-features = false, features = [ napi-derive = "2" next-swc = { version = "0.0.0", path = "../core" } next-dev = { workspace = true } +next-api = { workspace = true } next-build = { workspace = true } next-core = { workspace = true } turbo-tasks = { workspace = true } diff --git a/packages/next-swc/crates/napi/src/lib.rs b/packages/next-swc/crates/napi/src/lib.rs index db1dd3db698a5..3210abf6fcc8f 100644 --- a/packages/next-swc/crates/napi/src/lib.rs +++ b/packages/next-swc/crates/napi/src/lib.rs @@ -49,6 +49,7 @@ use turbopack_binding::swc::core::{ pub mod app_structure; pub mod mdx; pub mod minify; +pub mod next_api; pub mod parse; pub mod transform; pub mod turbopack; @@ -116,6 +117,7 @@ static REGISTER_ONCE: Once = Once::new(); fn register() { REGISTER_ONCE.call_once(|| { + ::next_api::register(); next_core::register(); include!(concat!(env!("OUT_DIR"), "/register.rs")); }); diff --git a/packages/next-swc/crates/napi/src/next_api/endpoint.rs b/packages/next-swc/crates/napi/src/next_api/endpoint.rs new file mode 100644 index 0000000000000..8aef6b3efff3e --- /dev/null +++ b/packages/next-swc/crates/napi/src/next_api/endpoint.rs @@ -0,0 +1,55 @@ +use napi::{bindgen_prelude::External, JsFunction}; +use next_api::route::{Endpoint, EndpointVc, WrittenEndpoint}; + +use super::utils::{subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc}; + +#[napi(object)] +pub struct NapiWrittenEndpoint { + pub server_entry_path: String, + pub server_paths: Vec, + pub issues: Vec, + pub diagnostics: Vec, +} + +impl From<&WrittenEndpoint> for NapiWrittenEndpoint { + fn from(written_endpoint: &WrittenEndpoint) -> Self { + Self { + server_entry_path: written_endpoint.server_entry_path.clone(), + server_paths: written_endpoint.server_paths.clone(), + issues: vec![], + diagnostics: vec![], + } + } +} + +#[napi] +pub async fn endpoint_write_to_disk( + #[napi(ts_arg_type = "{ __napiType: \"Endpoint\" }")] endpoint: External>, +) -> napi::Result { + let turbo_tasks = endpoint.turbo_tasks().clone(); + let endpoint = **endpoint; + let written = turbo_tasks + .run_once(async move { Ok(endpoint.write_to_disk().strongly_consistent().await?) }) + .await?; + // TODO peek_issues and diagnostics + Ok((&*written).into()) +} + +#[napi(ts_return_type = "{ __napiType: \"RootTask\" }")] +pub fn endpoint_changed_subscribe( + #[napi(ts_arg_type = "{ __napiType: \"Endpoint\" }")] endpoint: External>, + func: JsFunction, +) -> napi::Result> { + let turbo_tasks = endpoint.turbo_tasks().clone(); + let endpoint = **endpoint; + subscribe( + turbo_tasks, + func, + move || async move { + endpoint.changed().await?; + // TODO peek_issues and diagnostics + Ok(()) + }, + |_ctx| Ok(vec![()]), + ) +} diff --git a/packages/next-swc/crates/napi/src/next_api/mod.rs b/packages/next-swc/crates/napi/src/next_api/mod.rs new file mode 100644 index 0000000000000..eec6867524723 --- /dev/null +++ b/packages/next-swc/crates/napi/src/next_api/mod.rs @@ -0,0 +1,3 @@ +pub mod endpoint; +pub mod project; +pub mod utils; diff --git a/packages/next-swc/crates/napi/src/next_api/project.rs b/packages/next-swc/crates/napi/src/next_api/project.rs new file mode 100644 index 0000000000000..d03c69f355701 --- /dev/null +++ b/packages/next-swc/crates/napi/src/next_api/project.rs @@ -0,0 +1,195 @@ +use std::sync::Arc; + +use anyhow::Result; +use napi::{bindgen_prelude::External, JsFunction}; +use next_api::{ + project::{Middleware, ProjectOptions, ProjectVc}, + route::{EndpointVc, Route}, +}; +use turbo_tasks::TurboTasks; +use turbopack_binding::turbo::tasks_memory::MemoryBackend; + +use super::utils::{serde_enum_to_string, subscribe, RootTask, VcArc}; +use crate::register; + +#[napi(object)] +pub struct NapiProjectOptions { + /// A root path from which all files must be nested under. Trying to access + /// a file outside this root will fail. Think of this as a chroot. + pub root_path: String, + + /// A path inside the root_path which contains the app/pages directories. + pub project_path: String, + + /// Whether to watch he filesystem for file changes. + pub watch: bool, + + /// The contents of next.config.js, serialized to JSON. + pub next_config: String, + + /// An upper bound of memory that turbopack will attempt to stay under. + pub memory_limit: Option, +} + +impl Into for NapiProjectOptions { + fn into(self) -> ProjectOptions { + ProjectOptions { + root_path: self.root_path, + project_path: self.project_path, + watch: self.watch, + next_config: self.next_config, + memory_limit: self.memory_limit.map(|m| m as _), + } + } +} + +#[napi(ts_return_type = "{ __napiType: \"Project\" }")] +pub async fn project_new(options: NapiProjectOptions) -> napi::Result>> { + register(); + let turbo_tasks = TurboTasks::new(MemoryBackend::new( + options + .memory_limit + .map(|m| m as usize) + .unwrap_or(usize::MAX), + )); + let options = options.into(); + let project = turbo_tasks + .run_once(async move { Ok(ProjectVc::new(options).resolve().await?) }) + .await?; + Ok(External::new_with_size_hint( + VcArc::new(turbo_tasks, project), + 100, + )) +} + +#[napi(object)] +#[derive(Default)] +struct NapiRoute { + /// The relative path from project_path to the route file + pub pathname: String, + + /// The type of route, eg a Page or App + pub r#type: &'static str, + + // Different representations of the endpoint + pub endpoint: Option>>, + pub html_endpoint: Option>>, + pub rsc_endpoint: Option>>, + pub data_endpoint: Option>>, +} + +impl NapiRoute { + fn from_route( + pathname: String, + value: Route, + turbo_tasks: &Arc>, + ) -> Self { + let convert_endpoint = + |endpoint: EndpointVc| Some(External::new(VcArc::new(turbo_tasks.clone(), endpoint))); + match value { + Route::Page { + html_endpoint, + data_endpoint, + } => NapiRoute { + pathname, + r#type: "page", + html_endpoint: convert_endpoint(html_endpoint.clone()), + data_endpoint: convert_endpoint(data_endpoint.clone()), + ..Default::default() + }, + Route::PageApi { endpoint } => NapiRoute { + pathname, + r#type: "page-api", + endpoint: convert_endpoint(endpoint.clone()), + ..Default::default() + }, + Route::AppPage { + html_endpoint, + rsc_endpoint, + } => NapiRoute { + pathname, + r#type: "app-page", + html_endpoint: convert_endpoint(html_endpoint.clone()), + rsc_endpoint: convert_endpoint(rsc_endpoint.clone()), + ..Default::default() + }, + Route::AppRoute { endpoint } => NapiRoute { + pathname, + r#type: "app-route", + endpoint: convert_endpoint(endpoint.clone()), + ..Default::default() + }, + Route::Conflict => NapiRoute { + pathname, + r#type: "conflict", + ..Default::default() + }, + } + } +} + +#[napi(object)] +struct NapiMiddleware { + pub endpoint: External>, + pub runtime: String, + pub matcher: Option>, +} + +impl NapiMiddleware { + fn from_middleware( + value: &Middleware, + turbo_tasks: &Arc>, + ) -> Result { + Ok(NapiMiddleware { + endpoint: External::new(VcArc::new(turbo_tasks.clone(), value.endpoint.clone())), + runtime: serde_enum_to_string(&value.config.runtime)?, + matcher: value.config.matcher.clone(), + }) + } +} + +#[napi(object)] +struct NapiEntrypoints { + pub routes: Vec, + pub middleware: Option, + pub issues: Vec, + pub diagnostics: Vec, +} + +#[napi(ts_return_type = "{ __napiType: \"RootTask\" }")] +pub fn project_entrypoints_subscribe( + #[napi(ts_arg_type = "{ __napiType: \"Project\" }")] project: External>, + func: JsFunction, +) -> napi::Result> { + let turbo_tasks = project.turbo_tasks().clone(); + let project = **project; + subscribe( + turbo_tasks.clone(), + func, + move || async move { + let entrypoints = project.entrypoints(); + let entrypoints = entrypoints.strongly_consistent().await?; + // TODO peek_issues and diagnostics + Ok(entrypoints) + }, + move |ctx| { + let entrypoints = ctx.value; + Ok(vec![NapiEntrypoints { + routes: entrypoints + .routes + .iter() + .map(|(pathname, &route)| { + NapiRoute::from_route(pathname.clone(), route, &turbo_tasks) + }) + .collect::>(), + middleware: entrypoints + .middleware + .as_ref() + .map(|m| NapiMiddleware::from_middleware(&m, &turbo_tasks)) + .transpose()?, + issues: vec![], + diagnostics: vec![], + }]) + }, + ) +} diff --git a/packages/next-swc/crates/napi/src/next_api/utils.rs b/packages/next-swc/crates/napi/src/next_api/utils.rs new file mode 100644 index 0000000000000..fa59e0d8e8ec1 --- /dev/null +++ b/packages/next-swc/crates/napi/src/next_api/utils.rs @@ -0,0 +1,135 @@ +use std::{future::Future, ops::Deref, sync::Arc}; + +use anyhow::{anyhow, bail, Context, Result}; +use napi::{ + bindgen_prelude::{External, ToNapiValue}, + threadsafe_function::{ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode}, + JsFunction, JsObject, NapiRaw, NapiValue, Status, +}; +use serde::Serialize; +use turbo_tasks::{NothingVc, TaskId, TurboTasks}; +use turbopack_binding::{ + turbo::tasks_memory::MemoryBackend, turbopack::core::error::PrettyPrintError, +}; + +/// A helper type to hold both a Vc operation and the TurboTasks root process. +/// Without this, we'd need to pass both individually all over the place +#[derive(Clone)] +pub struct VcArc { + turbo_tasks: Arc>, + /// The Vc. Must be resolved, otherwise you are referencing an inactive + /// operation. + vc: T, +} + +impl VcArc { + pub fn new(turbo_tasks: Arc>, vc: T) -> Self { + Self { turbo_tasks, vc } + } + + pub fn turbo_tasks(&self) -> &Arc> { + &self.turbo_tasks + } +} + +impl Deref for VcArc { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.vc + } +} + +pub fn serde_enum_to_string(value: &T) -> Result { + Ok(serde_json::to_value(value)? + .as_str() + .context("value must serialize to a string")? + .to_string()) +} + +/// The root of our turbopack computation. +pub struct RootTask { + turbo_tasks: Arc>, + task_id: Option, +} + +impl Drop for RootTask { + fn drop(&mut self) { + // TODO stop the root task + } +} + +#[napi] +pub fn root_task_dispose( + #[napi(ts_arg_type = "{ __napiType: \"RootTask\" }")] _root_task: External, +) -> napi::Result<()> { + // TODO(alexkirsz) Implement. Not panicking here to avoid crashing the process + // when testing. + eprintln!("root_task_dispose not yet implemented"); + Ok(()) +} + +#[napi(object)] +pub struct NapiIssue {} + +#[napi(object)] +pub struct NapiDiagnostic {} + +pub struct TurbopackResult { + pub result: T, + pub issues: Vec, + pub diagnostics: Vec, +} + +impl ToNapiValue for TurbopackResult { + unsafe fn to_napi_value( + env: napi::sys::napi_env, + val: Self, + ) -> napi::Result { + let result = T::to_napi_value(env, val.result)?; + // let issues = ToNapiValue::to_napi_value(env, val.issues)?; + // let diagnostics = ToNapiValue::to_napi_value(env, val.diagnostics)?; + + let result = JsObject::from_raw(env, result)?; + + let mut obj = napi::Env::from_raw(env).create_object()?; + for key in JsObject::keys(&result)? { + obj.set_named_property(&key, result.get_named_property(&key)?)?; + } + obj.set_named_property("issues", val.issues)?; + obj.set_named_property("diagnostics", val.diagnostics)?; + + Ok(obj.raw()) + } +} + +pub fn subscribe> + Send, V: ToNapiValue>( + turbo_tasks: Arc>, + func: JsFunction, + handler: impl 'static + Sync + Send + Clone + Fn() -> F, + mapper: impl 'static + Sync + Send + FnMut(ThreadSafeCallContext) -> napi::Result>, +) -> napi::Result> { + let func: ThreadsafeFunction = func.create_threadsafe_function(0, mapper)?; + let task_id = turbo_tasks.spawn_root_task(move || { + let handler = handler.clone(); + let func = func.clone(); + Box::pin(async move { + let result = handler().await; + + let status = func.call( + result.map_err(|e| napi::Error::from_reason(PrettyPrintError(&e).to_string())), + ThreadsafeFunctionCallMode::NonBlocking, + ); + if !matches!(status, Status::Ok) { + let error = anyhow!("Error calling JS function: {}", status); + eprintln!("{}", error); + return Err(error); + } + Ok(NothingVc::new().into()) + }) + }); + Ok(External::new(RootTask { + turbo_tasks, + task_id: Some(task_id), + })) +} diff --git a/packages/next-swc/crates/next-api/Cargo.toml b/packages/next-swc/crates/next-api/Cargo.toml new file mode 100644 index 0000000000000..f3382ab2a7d4b --- /dev/null +++ b/packages/next-swc/crates/next-api/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "next-api" +version = "0.1.0" +description = "TBD" +license = "MPL-2.0" +edition = "2021" +autobenches = false + +[lib] +bench = false + +[features] +default = ["custom_allocator", "native-tls"] +custom_allocator = ["turbopack-binding/__turbo_tasks_malloc", "turbopack-binding/__turbo_tasks_malloc_custom_allocator"] +native-tls = ["next-core/native-tls"] +rustls-tls = ["next-core/rustls-tls"] + +[dependencies] +anyhow = { workspace = true, features = ["backtrace"] } +futures = { workspace = true } +indexmap = { workspace = true } +next-core = { workspace = true } +once_cell = { workspace = true } +serde = { workspace = true } +tokio = { workspace = true, features = ["full"] } +turbopack-binding = { workspace = true, features = [ + "__turbo_tasks_memory", + "__turbo_tasks_env", + "__turbo_tasks_fs", + "__turbopack", + "__turbopack_build", + "__turbopack_core", + "__turbopack_dev", + "__turbopack_env", + "__turbopack_cli_utils", + "__turbopack_node", + "__turbopack_dev_server", +]} +turbo-tasks = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter", "json"] } + +[build-dependencies] +turbopack-binding = { workspace = true, features = [ + "__turbo_tasks_build" +]} \ No newline at end of file diff --git a/packages/next-swc/crates/next-api/build.rs b/packages/next-swc/crates/next-api/build.rs new file mode 100644 index 0000000000000..23e4bcb55d922 --- /dev/null +++ b/packages/next-swc/crates/next-api/build.rs @@ -0,0 +1,5 @@ +use turbopack_binding::turbo::tasks_build::generate_register; + +fn main() { + generate_register(); +} diff --git a/packages/next-swc/crates/next-api/src/app.rs b/packages/next-swc/crates/next-api/src/app.rs new file mode 100644 index 0000000000000..689c67b435d2e --- /dev/null +++ b/packages/next-swc/crates/next-api/src/app.rs @@ -0,0 +1,67 @@ +use next_core::app_structure::Entrypoint; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{trace::TraceRawVcs, CompletionVc}; + +use crate::route::{Endpoint, EndpointVc, Route, RouteVc, WrittenEndpointVc}; + +#[turbo_tasks::function] +pub async fn app_entry_point_to_route(entrypoint: Entrypoint) -> RouteVc { + match entrypoint { + Entrypoint::AppPage { .. } => Route::AppPage { + html_endpoint: AppPageEndpoint { + ty: AppPageEndpointType::Html, + } + .cell() + .into(), + rsc_endpoint: AppPageEndpoint { + ty: AppPageEndpointType::Rsc, + } + .cell() + .into(), + }, + Entrypoint::AppRoute { .. } => Route::AppRoute { + endpoint: AppRouteEndpoint.cell().into(), + }, + } + .cell() +} + +#[derive(Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Debug, TraceRawVcs)] +enum AppPageEndpointType { + Html, + Rsc, +} + +#[turbo_tasks::value] +struct AppPageEndpoint { + ty: AppPageEndpointType, +} + +#[turbo_tasks::value_impl] +impl Endpoint for AppPageEndpoint { + #[turbo_tasks::function] + fn write_to_disk(&self) -> WrittenEndpointVc { + todo!() + } + + #[turbo_tasks::function] + fn changed(&self) -> CompletionVc { + todo!() + } +} + +#[turbo_tasks::value] +struct AppRouteEndpoint; + +#[turbo_tasks::value_impl] +impl Endpoint for AppRouteEndpoint { + #[turbo_tasks::function] + fn write_to_disk(&self) -> WrittenEndpointVc { + todo!() + } + + #[turbo_tasks::function] + fn changed(&self) -> CompletionVc { + todo!() + } +} diff --git a/packages/next-swc/crates/next-api/src/lib.rs b/packages/next-swc/crates/next-api/src/lib.rs new file mode 100644 index 0000000000000..56e847a19be2c --- /dev/null +++ b/packages/next-swc/crates/next-api/src/lib.rs @@ -0,0 +1,13 @@ +#![feature(future_join)] +#![feature(min_specialization)] + +mod app; +mod pages; +pub mod project; +pub mod route; + +pub fn register() { + next_core::register(); + turbopack_binding::turbopack::build::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/packages/next-swc/crates/next-api/src/pages.rs b/packages/next-swc/crates/next-api/src/pages.rs new file mode 100644 index 0000000000000..066d704ef9665 --- /dev/null +++ b/packages/next-swc/crates/next-api/src/pages.rs @@ -0,0 +1,361 @@ +use anyhow::{bail, Context, Result}; +use indexmap::IndexMap; +use next_core::{ + create_page_loader_entry_module, emit_all_assets, get_asset_path_from_pathname, + pages_structure::{ + PagesDirectoryStructure, PagesDirectoryStructureVc, PagesStructure, PagesStructureItem, + PagesStructureVc, + }, +}; +use turbo_tasks::{primitives::StringVc, CompletionVc, CompletionsVc, Value}; +use turbopack_binding::{ + turbo::tasks_fs::FileSystemPathVc, + turbopack::{ + core::{ + asset::{Asset, AssetVc, AssetsVc}, + changed::{any_content_changed, any_content_changed_of_assets}, + chunk::{ChunkableModule, ChunkingContext}, + context::AssetContext, + file_source::FileSourceVc, + reference_type::{EntryReferenceSubType, ReferenceType}, + source::SourceVc, + }, + ecmascript::EcmascriptModuleAssetVc, + }, +}; + +use crate::{ + project::ProjectVc, + route::{Endpoint, EndpointVc, Route, RoutesVc, WrittenEndpoint, WrittenEndpointVc}, +}; + +#[turbo_tasks::function] +pub async fn get_pages_routes( + project: ProjectVc, + page_structure: PagesStructureVc, +) -> Result { + let PagesStructure { api, pages, .. } = *page_structure.await?; + let mut routes = IndexMap::new(); + async fn add_dir_to_routes( + routes: &mut IndexMap, + dir: PagesDirectoryStructureVc, + make_route: impl Fn(StringVc, StringVc, FileSystemPathVc) -> Route, + ) -> Result<()> { + let mut queue = vec![dir]; + while let Some(dir) = queue.pop() { + let PagesDirectoryStructure { + ref items, + ref children, + next_router_path: _, + project_path: _, + } = *dir.await?; + for &item in items.iter() { + let PagesStructureItem { + next_router_path, + project_path, + original_path, + } = *item.await?; + let pathname = format!("/{}", next_router_path.await?.path); + let pathname_vc = StringVc::cell(pathname.clone()); + let original_name = StringVc::cell(format!("/{}", original_path.await?.path)); + let route = make_route(pathname_vc, original_name, project_path); + routes.insert(pathname, route); + } + for &child in children.iter() { + queue.push(child); + } + } + Ok(()) + } + if let Some(api) = api { + add_dir_to_routes(&mut routes, api, |pathname, original_name, path| { + Route::PageApi { + endpoint: ApiEndpointVc::new(project, pathname, original_name, path).into(), + } + }) + .await?; + } + if let Some(page) = pages { + add_dir_to_routes(&mut routes, page, |pathname, original_name, path| { + Route::Page { + html_endpoint: PageHtmlEndpointVc::new( + project, + pathname.clone(), + original_name.clone(), + path, + ) + .into(), + data_endpoint: PageDataEndpointVc::new(project, pathname, original_name, path) + .into(), + } + }) + .await?; + } + Ok(RoutesVc::cell(routes)) +} + +#[turbo_tasks::value] +struct PageHtmlEndpoint { + project: ProjectVc, + pathname: StringVc, + original_name: StringVc, + path: FileSystemPathVc, +} + +#[turbo_tasks::value_impl] +impl PageHtmlEndpointVc { + #[turbo_tasks::function] + fn new( + project: ProjectVc, + pathname: StringVc, + original_name: StringVc, + path: FileSystemPathVc, + ) -> Self { + PageHtmlEndpoint { + project, + pathname, + original_name, + path, + } + .cell() + } + + #[turbo_tasks::function] + async fn source(self) -> Result { + let this = self.await?; + Ok(FileSourceVc::new(this.path).into()) + } + + #[turbo_tasks::function] + async fn client_chunks(self) -> Result { + let this = self.await?; + + let client_module = create_page_loader_entry_module( + this.project.pages_client_module_context(), + self.source(), + this.pathname, + ); + + let Some(client_module) = EcmascriptModuleAssetVc::resolve_from(client_module).await? + else { + bail!("expected an ECMAScript module asset"); + }; + + let client_chunking_context = this.project.client_chunking_context(); + + let client_entry_chunk = client_module.as_root_chunk(client_chunking_context.into()); + + let client_chunks = client_chunking_context.evaluated_chunk_group( + client_entry_chunk, + this.project + .pages_client_runtime_entries() + .with_entry(client_module.into()), + ); + + Ok(client_chunks) + } + + #[turbo_tasks::function] + async fn ssr_chunk(self) -> Result { + let this = self.await?; + let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page)); + + let ssr_module = this + .project + .pages_ssr_module_context() + .process(self.source(), reference_type.clone()); + + let Some(ssr_module) = EcmascriptModuleAssetVc::resolve_from(ssr_module).await? else { + bail!("expected an ECMAScript module asset"); + }; + + let asset_path = get_asset_path_from_pathname(&this.pathname.await?, ".js"); + + let ssr_entry_chunk_path_string = format!("server/pages{asset_path}"); + let ssr_entry_chunk_path = this.project.node_root().join(&ssr_entry_chunk_path_string); + let ssr_entry_chunk = this.project.ssr_chunking_context().entry_chunk( + ssr_entry_chunk_path, + ssr_module.into(), + this.project.pages_ssr_runtime_entries(), + ); + + Ok(ssr_entry_chunk) + } +} + +#[turbo_tasks::value_impl] +impl Endpoint for PageHtmlEndpoint { + #[turbo_tasks::function] + async fn write_to_disk(self_vc: PageHtmlEndpointVc) -> Result { + let this = self_vc.await?; + let ssr_chunk = self_vc.ssr_chunk(); + let ssr_emit = emit_all_assets( + AssetsVc::cell(vec![ssr_chunk]), + this.project.node_root(), + this.project.client_root().join("_next"), + this.project.node_root(), + ); + let client_emit = emit_all_assets( + self_vc.client_chunks(), + this.project.node_root(), + this.project.client_root().join("_next"), + this.project.node_root(), + ); + + ssr_emit.await?; + client_emit.await?; + + Ok(WrittenEndpoint { + server_entry_path: this + .project + .node_root() + .await? + .get_path_to(&*ssr_chunk.ident().path().await?) + .context("ssr chunk entry path must be inside the node root")? + .to_string(), + server_paths: vec![], + } + .cell()) + } + + #[turbo_tasks::function] + fn changed(self_vc: PageHtmlEndpointVc) -> CompletionVc { + let ssr_chunk = self_vc.ssr_chunk(); + CompletionsVc::all(vec![ + any_content_changed(ssr_chunk), + any_content_changed_of_assets(self_vc.client_chunks()), + ]) + } +} + +#[turbo_tasks::value] +struct PageDataEndpoint { + project: ProjectVc, + pathname: StringVc, + original_name: StringVc, + path: FileSystemPathVc, +} + +#[turbo_tasks::value_impl] +impl PageDataEndpointVc { + #[turbo_tasks::function] + fn new( + project: ProjectVc, + pathname: StringVc, + original_name: StringVc, + path: FileSystemPathVc, + ) -> Self { + PageDataEndpoint { + project, + pathname, + original_name, + path, + } + .cell() + } + + #[turbo_tasks::function] + async fn ssr_data_chunk(self) -> Result { + let this = self.await?; + let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page)); + + let ssr_data_module = this + .project + .pages_ssr_data_module_context() + .process(self.source(), reference_type.clone()); + + let Some(ssr_data_module) = EcmascriptModuleAssetVc::resolve_from(ssr_data_module).await? + else { + bail!("expected an ECMAScript module asset"); + }; + + let asset_path = get_asset_path_from_pathname(&this.pathname.await?, ".js"); + + let ssr_data_entry_chunk_path_string = format!("server/pages-data/{asset_path}"); + let ssr_data_entry_chunk_path = this + .project + .node_root() + .join(&ssr_data_entry_chunk_path_string); + let ssr_data_entry_chunk = this.project.ssr_data_chunking_context().entry_chunk( + ssr_data_entry_chunk_path, + ssr_data_module.into(), + this.project.pages_ssr_runtime_entries(), + ); + + Ok(ssr_data_entry_chunk) + } +} + +#[turbo_tasks::value_impl] +impl Endpoint for PageDataEndpoint { + #[turbo_tasks::function] + async fn write_to_disk(self_vc: PageDataEndpointVc) -> Result { + let this = self_vc.await?; + let ssr_data_chunk = self_vc.ssr_data_chunk(); + emit_all_assets( + AssetsVc::cell(vec![ssr_data_chunk]), + this.project.node_root(), + this.project.client_root().join("_next"), + this.project.node_root(), + ) + .await?; + + Ok(WrittenEndpoint { + server_entry_path: this + .project + .node_root() + .await? + .get_path_to(&*ssr_data_chunk.ident().path().await?) + .context("ssr data chunk entry path must be inside the node root")? + .to_string(), + server_paths: vec![], + } + .cell()) + } + + #[turbo_tasks::function] + async fn changed(self_vc: PageDataEndpointVc) -> Result { + let ssr_data_chunk = self_vc.ssr_data_chunk(); + Ok(any_content_changed(ssr_data_chunk)) + } +} + +#[turbo_tasks::value] +struct ApiEndpoint { + project: ProjectVc, + pathname: StringVc, + original_name: StringVc, + path: FileSystemPathVc, +} + +#[turbo_tasks::value_impl] +impl ApiEndpointVc { + #[turbo_tasks::function] + fn new( + project: ProjectVc, + pathname: StringVc, + original_name: StringVc, + path: FileSystemPathVc, + ) -> Self { + ApiEndpoint { + project, + pathname, + original_name, + path, + } + .cell() + } +} + +#[turbo_tasks::value_impl] +impl Endpoint for ApiEndpoint { + #[turbo_tasks::function] + fn write_to_disk(&self) -> WrittenEndpointVc { + todo!() + } + + #[turbo_tasks::function] + fn changed(&self) -> CompletionVc { + todo!() + } +} diff --git a/packages/next-swc/crates/next-api/src/project.rs b/packages/next-swc/crates/next-api/src/project.rs new file mode 100644 index 0000000000000..67cbf9c536cbb --- /dev/null +++ b/packages/next-swc/crates/next-api/src/project.rs @@ -0,0 +1,517 @@ +use std::path::MAIN_SEPARATOR; + +use anyhow::{Context, Result}; +use indexmap::{map::Entry, IndexMap}; +use next_core::{ + app_structure::{find_app_dir, get_entrypoints}, + mode::NextMode, + next_client::{ + get_client_chunking_context, get_client_compile_time_info, + get_client_module_options_context, get_client_resolve_options_context, + get_client_runtime_entries, ClientContextType, + }, + next_config::NextConfigVc, + next_dynamic::NextDynamicTransitionVc, + next_server::{ + get_server_chunking_context, get_server_compile_time_info, + get_server_module_options_context, get_server_resolve_options_context, + get_server_runtime_entries, ServerContextType, + }, + pages_structure::{find_pages_structure, PagesStructureVc}, + util::NextSourceConfig, +}; +use serde::{Deserialize, Serialize}; +use turbo_tasks::{ + debug::ValueDebugFormat, trace::TraceRawVcs, NothingVc, TaskInput, TransientValue, + TryJoinIterExt, Value, +}; +use turbopack_binding::{ + turbo::{ + tasks_env::ProcessEnvVc, + tasks_fs::{ + DiskFileSystemVc, FileSystem, FileSystemPathVc, FileSystemVc, VirtualFileSystemVc, + }, + }, + turbopack::{ + build::BuildChunkingContextVc, + core::{ + chunk::{ChunkingContext, EvaluatableAssetsVc}, + compile_time_info::CompileTimeInfoVc, + context::AssetContextVc, + environment::ServerAddrVc, + PROJECT_FILESYSTEM_NAME, + }, + dev::DevChunkingContextVc, + ecmascript::chunk::EcmascriptChunkingContextVc, + env::dotenv::load_env, + node::execution_context::ExecutionContextVc, + turbopack::{ + evaluate_context::node_build_environment, + module_options::ModuleOptionsContextVc, + resolve_options_context::ResolveOptionsContextVc, + transition::{ContextTransitionVc, TransitionsByNameVc}, + ModuleAssetContextVc, + }, + }, +}; + +use crate::{ + app::app_entry_point_to_route, + pages::get_pages_routes, + route::{EndpointVc, Route}, +}; + +#[derive(Debug, Serialize, Deserialize, Clone, TaskInput)] +#[serde(rename_all = "camelCase")] +pub struct ProjectOptions { + /// A root path from which all files must be nested under. Trying to access + /// a file outside this root will fail. Think of this as a chroot. + pub root_path: String, + + /// A path inside the root_path which contains the app/pages directories. + pub project_path: String, + + /// The contents of next.config.js, serialized to JSON. + pub next_config: String, + + /// Whether to watch the filesystem for file changes. + pub watch: bool, + + /// An upper bound of memory that turbopack will attempt to stay under. + pub memory_limit: Option, +} + +#[derive(Serialize, Deserialize, TraceRawVcs, PartialEq, Eq, ValueDebugFormat)] +pub struct Middleware { + pub endpoint: EndpointVc, + pub config: NextSourceConfig, +} + +#[turbo_tasks::value] +pub struct Entrypoints { + pub routes: IndexMap, + pub middleware: Option, +} + +#[turbo_tasks::value] +pub struct Project { + /// A root path from which all files must be nested under. Trying to access + /// a file outside this root will fail. Think of this as a chroot. + root_path: String, + + /// A path inside the root_path which contains the app/pages directories. + project_path: String, + + /// Whether to watch the filesystem for file changes. + watch: bool, + + /// Next config. + next_config: NextConfigVc, + + browserslist_query: String, + + mode: NextMode, +} + +#[turbo_tasks::value_impl] +impl ProjectVc { + #[turbo_tasks::function] + pub async fn new(options: ProjectOptions) -> Result { + let next_config = NextConfigVc::from_string(options.next_config); + Ok(Project { + root_path: options.root_path, + project_path: options.project_path, + watch: options.watch, + next_config, + browserslist_query: "last 1 Chrome versions, last 1 Firefox versions, last 1 Safari \ + versions, last 1 Edge versions" + .to_string(), + mode: NextMode::Development, + } + .cell()) + } + + #[turbo_tasks::function] + async fn project_fs(self) -> Result { + let this = self.await?; + let disk_fs = DiskFileSystemVc::new( + PROJECT_FILESYSTEM_NAME.to_string(), + this.root_path.to_string(), + ); + if this.watch { + disk_fs.await?.start_watching_with_invalidation_reason()?; + } + Ok(disk_fs.into()) + } + + #[turbo_tasks::function] + async fn client_fs(self) -> Result { + let virtual_fs = VirtualFileSystemVc::new(); + Ok(virtual_fs.into()) + } + + #[turbo_tasks::function] + async fn node_fs(self) -> Result { + let this = self.await?; + let disk_fs = DiskFileSystemVc::new("node".to_string(), this.project_path.clone()); + disk_fs.await?.start_watching_with_invalidation_reason()?; + Ok(disk_fs.into()) + } + + #[turbo_tasks::function] + pub(super) fn node_root(self) -> FileSystemPathVc { + self.node_fs().root().join(".next") + } + + #[turbo_tasks::function] + pub(super) fn client_root(self) -> FileSystemPathVc { + self.client_fs().root() + } + + #[turbo_tasks::function] + fn project_root_path(self) -> FileSystemPathVc { + self.project_fs().root() + } + + #[turbo_tasks::function] + async fn project_path(self) -> Result { + let this = self.await?; + let root = self.project_root_path(); + let project_relative = this.project_path.strip_prefix(&this.root_path).unwrap(); + let project_relative = project_relative + .strip_prefix(MAIN_SEPARATOR) + .unwrap_or(project_relative) + .replace(MAIN_SEPARATOR, "/"); + Ok(root.join(&project_relative)) + } + + #[turbo_tasks::function] + async fn pages_structure(self) -> Result { + let this: turbo_tasks::ReadRef = self.await?; + let next_router_fs = VirtualFileSystemVc::new().as_file_system(); + let next_router_root = next_router_fs.root(); + Ok(find_pages_structure( + self.project_path(), + next_router_root, + this.next_config.page_extensions(), + )) + } + + #[turbo_tasks::function] + fn env(self) -> ProcessEnvVc { + load_env(self.project_path()) + } + + #[turbo_tasks::function] + async fn next_config(self) -> Result { + Ok(self.await?.next_config) + } + + #[turbo_tasks::function] + fn execution_context(self) -> ExecutionContextVc { + let node_root = self.node_root(); + + let node_execution_chunking_context = DevChunkingContextVc::builder( + self.project_path(), + node_root, + node_root.join("chunks"), + node_root.join("assets"), + node_build_environment(), + ) + .build() + .into(); + + ExecutionContextVc::new( + self.project_path(), + node_execution_chunking_context, + self.env(), + ) + } + + #[turbo_tasks::function] + async fn client_compile_time_info(self) -> Result { + let this = self.await?; + Ok(get_client_compile_time_info( + this.mode, + &this.browserslist_query, + )) + } + + #[turbo_tasks::function] + async fn server_compile_time_info(self) -> Result { + let this = self.await?; + Ok(get_server_compile_time_info( + this.mode, + self.env(), + // TODO(alexkirsz) Fill this out. + ServerAddrVc::empty(), + )) + } + + #[turbo_tasks::function] + async fn pages_dir(self) -> Result { + Ok(if let Some(pages) = self.pages_structure().await?.pages { + pages.project_path() + } else { + self.project_path().join("pages") + }) + } + + #[turbo_tasks::function] + fn pages_transitions(self) -> TransitionsByNameVc { + TransitionsByNameVc::cell( + [( + "next-dynamic".to_string(), + NextDynamicTransitionVc::new(self.pages_client_transition()).into(), + )] + .into_iter() + .collect(), + ) + } + + #[turbo_tasks::function] + fn pages_client_transition(self) -> ContextTransitionVc { + ContextTransitionVc::new( + self.client_compile_time_info(), + self.pages_client_module_options_context(), + self.pages_client_resolve_options_context(), + ) + } + + #[turbo_tasks::function] + async fn pages_client_module_options_context(self) -> Result { + let this = self.await?; + Ok(get_client_module_options_context( + self.project_path(), + self.execution_context(), + self.client_compile_time_info().environment(), + Value::new(ClientContextType::Pages { + pages_dir: self.pages_dir(), + }), + this.mode, + self.next_config(), + )) + } + + #[turbo_tasks::function] + async fn pages_client_resolve_options_context(self) -> Result { + let this = self.await?; + Ok(get_client_resolve_options_context( + self.project_path(), + Value::new(ClientContextType::Pages { + pages_dir: self.pages_dir(), + }), + this.mode, + self.next_config(), + self.execution_context(), + )) + } + + #[turbo_tasks::function] + pub(super) fn pages_client_module_context(self) -> AssetContextVc { + ModuleAssetContextVc::new( + self.pages_transitions(), + self.client_compile_time_info(), + self.pages_client_module_options_context(), + self.pages_client_resolve_options_context(), + ) + .into() + } + + #[turbo_tasks::function] + pub(super) fn pages_ssr_module_context(self) -> AssetContextVc { + ModuleAssetContextVc::new( + self.pages_transitions(), + self.server_compile_time_info(), + self.pages_ssr_module_options_context(), + self.pages_ssr_resolve_options_context(), + ) + .into() + } + + #[turbo_tasks::function] + pub(super) fn pages_ssr_data_module_context(self) -> AssetContextVc { + ModuleAssetContextVc::new( + self.pages_transitions(), + self.server_compile_time_info(), + self.pages_ssr_data_module_options_context(), + self.pages_ssr_resolve_options_context(), + ) + .into() + } + + #[turbo_tasks::function] + async fn pages_ssr_module_options_context(self) -> Result { + let this = self.await?; + Ok(get_server_module_options_context( + self.project_path(), + self.execution_context(), + Value::new(ServerContextType::Pages { + pages_dir: self.pages_dir(), + }), + this.mode, + self.next_config(), + )) + } + + #[turbo_tasks::function] + async fn pages_ssr_data_module_options_context(self) -> Result { + let this = self.await?; + Ok(get_server_module_options_context( + self.project_path(), + self.execution_context(), + Value::new(ServerContextType::PagesData { + pages_dir: self.pages_dir(), + }), + this.mode, + self.next_config(), + )) + } + + #[turbo_tasks::function] + async fn pages_ssr_resolve_options_context(self) -> Result { + let this = self.await?; + Ok(get_server_resolve_options_context( + self.project_path(), + Value::new(ServerContextType::Pages { + pages_dir: self.pages_dir(), + }), + this.mode, + self.next_config(), + self.execution_context(), + )) + } + + #[turbo_tasks::function] + pub(super) async fn pages_client_runtime_entries(self) -> Result { + let this = self.await?; + let client_runtime_entries = get_client_runtime_entries( + self.project_path(), + self.env(), + Value::new(ClientContextType::Pages { + pages_dir: self.pages_dir(), + }), + this.mode, + self.next_config(), + self.execution_context(), + ); + Ok(client_runtime_entries.resolve_entries(self.pages_client_module_context())) + } + + #[turbo_tasks::function] + pub(super) async fn pages_ssr_runtime_entries(self) -> Result { + let this = self.await?; + let ssr_runtime_entries = get_server_runtime_entries( + self.project_path(), + self.env(), + Value::new(ServerContextType::Pages { + pages_dir: self.pages_dir(), + }), + this.mode, + self.next_config(), + ); + Ok(ssr_runtime_entries.resolve_entries(self.pages_ssr_module_context())) + } + + #[turbo_tasks::function] + pub(super) async fn client_chunking_context(self) -> Result { + let this = self.await?; + Ok(get_client_chunking_context( + self.project_path(), + self.client_root(), + self.client_compile_time_info().environment(), + this.mode, + )) + } + + #[turbo_tasks::function] + pub(super) fn server_chunking_context(self) -> BuildChunkingContextVc { + get_server_chunking_context( + self.project_path(), + self.node_root(), + self.client_fs().root(), + self.server_compile_time_info().environment(), + ) + } + + #[turbo_tasks::function] + pub(super) async fn ssr_chunking_context(self) -> Result { + let ssr_chunking_context = self.server_chunking_context().with_layer("ssr"); + BuildChunkingContextVc::resolve_from(ssr_chunking_context) + .await? + .context("with_layer should not change the type of the chunking context") + } + + #[turbo_tasks::function] + pub(super) async fn ssr_data_chunking_context(self) -> Result { + let ssr_chunking_context = self.server_chunking_context().with_layer("ssr data"); + BuildChunkingContextVc::resolve_from(ssr_chunking_context) + .await? + .context("with_layer should not change the type of the chunking context") + } + + #[turbo_tasks::function] + pub(super) async fn rsc_chunking_context(self) -> Result { + let rsc_chunking_context = self.server_chunking_context().with_layer("rsc"); + BuildChunkingContextVc::resolve_from(rsc_chunking_context) + .await? + .context("with_layer should not change the type of the chunking context") + } + + /// Scans the app/pages directories for entry points files (matching the + /// provided page_extensions). + #[turbo_tasks::function] + pub async fn entrypoints(self) -> Result { + let this = self.await?; + let mut routes = IndexMap::new(); + if let Some(app_dir) = *find_app_dir(self.project_path()).await? { + let app_entrypoints = get_entrypoints(app_dir, this.next_config.page_extensions()); + routes.extend( + app_entrypoints + .await? + .iter() + .map(|(pathname, app_entrypoint)| async { + Ok(( + pathname.clone(), + *app_entry_point_to_route(*app_entrypoint).await?, + )) + }) + .try_join() + .await?, + ); + } + for (pathname, page_route) in get_pages_routes(self, self.pages_structure()).await?.iter() { + match routes.entry(pathname.clone()) { + Entry::Occupied(mut entry) => { + *entry.get_mut() = Route::Conflict; + } + Entry::Vacant(entry) => { + entry.insert(*page_route); + } + } + } + // TODO middleware + Ok(Entrypoints { + routes, + middleware: None, + } + .cell()) + } + + /// Emits opaque HMR events whenever a change is detected in the chunk group + /// internally known as `identifier`. + #[turbo_tasks::function] + pub fn hmr_events(self, _identifier: String, _sender: TransientValue<()>) -> NothingVc { + NothingVc::new() + } +} + +#[turbo_tasks::function] +async fn project_fs(project_dir: &str, watching: bool) -> Result { + let disk_fs = + DiskFileSystemVc::new(PROJECT_FILESYSTEM_NAME.to_string(), project_dir.to_string()); + if watching { + disk_fs.await?.start_watching_with_invalidation_reason()?; + } + Ok(disk_fs.into()) +} diff --git a/packages/next-swc/crates/next-api/src/route.rs b/packages/next-swc/crates/next-api/src/route.rs new file mode 100644 index 0000000000000..e4aa105f83183 --- /dev/null +++ b/packages/next-swc/crates/next-api/src/route.rs @@ -0,0 +1,43 @@ +use anyhow::Result; +use indexmap::IndexMap; +use turbo_tasks::CompletionVc; + +#[turbo_tasks::value(shared)] +#[derive(Copy, Clone, Debug)] +pub enum Route { + Page { + html_endpoint: EndpointVc, + data_endpoint: EndpointVc, + }, + PageApi { + endpoint: EndpointVc, + }, + AppPage { + html_endpoint: EndpointVc, + rsc_endpoint: EndpointVc, + }, + AppRoute { + endpoint: EndpointVc, + }, + Conflict, +} + +#[turbo_tasks::value_trait] +pub trait Endpoint { + fn write_to_disk(&self) -> WrittenEndpointVc; + fn changed(&self) -> CompletionVc; +} + +#[turbo_tasks::value(shared)] +#[derive(Debug)] +pub struct WrittenEndpoint { + /// Relative to the root_path + pub server_entry_path: String, + /// Relative to the root_path + pub server_paths: Vec, +} + +/// The routes as map from pathname to route. (pathname includes the leading +/// slash) +#[turbo_tasks::value(transparent)] +pub struct Routes(IndexMap); diff --git a/packages/next-swc/crates/next-build/src/next_pages/page_entries.rs b/packages/next-swc/crates/next-build/src/next_pages/page_entries.rs index 2772f5846cdd7..5dba2ece0eb6d 100644 --- a/packages/next-swc/crates/next-build/src/next_pages/page_entries.rs +++ b/packages/next-swc/crates/next-build/src/next_pages/page_entries.rs @@ -68,7 +68,11 @@ pub async fn get_page_entries( server_compile_time_info: CompileTimeInfoVc, next_config: NextConfigVc, ) -> Result { - let pages_structure = find_pages_structure(project_root, next_router_root, next_config); + let pages_structure = find_pages_structure( + project_root, + next_router_root, + next_config.page_extensions(), + ); let pages_dir = if let Some(pages) = pages_structure.await?.pages { pages.project_path().resolve().await? diff --git a/packages/next-swc/crates/next-core/js/src/entry/config/next.js b/packages/next-swc/crates/next-core/js/src/entry/config/next.js index c18ddc462aa29..3a985cd60df71 100644 --- a/packages/next-swc/crates/next-core/js/src/entry/config/next.js +++ b/packages/next-swc/crates/next-core/js/src/entry/config/next.js @@ -16,10 +16,6 @@ const loadNextConfig = async (silent) => { const customRoutes = await loadCustomRoutes(nextConfig) - nextConfig.headers = customRoutes.headers - nextConfig.rewrites = customRoutes.rewrites - nextConfig.redirects = customRoutes.redirects - // TODO: these functions takes arguments, have to be supported in a different way nextConfig.exportPathMap = nextConfig.exportPathMap && {} nextConfig.webpack = nextConfig.webpack && {} @@ -30,7 +26,10 @@ const loadNextConfig = async (silent) => { ) } - return nextConfig + return { + customRoutes: customRoutes, + config: nextConfig, + } } export { loadNextConfig as default } diff --git a/packages/next-swc/crates/next-core/src/app_structure.rs b/packages/next-swc/crates/next-core/src/app_structure.rs index fdb279d01e8ef..3ab0ce0bd9757 100644 --- a/packages/next-swc/crates/next-core/src/app_structure.rs +++ b/packages/next-swc/crates/next-core/src/app_structure.rs @@ -12,7 +12,7 @@ use turbo_tasks::{ debug::ValueDebugFormat, primitives::{StringVc, StringsVc}, trace::TraceRawVcs, - CompletionVc, CompletionsVc, + CompletionVc, CompletionsVc, TaskInput, ValueToString, }; use turbopack_binding::{ turbo::tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPathVc}, @@ -297,11 +297,11 @@ fn match_metadata_file<'a>( #[turbo_tasks::function] async fn get_directory_tree( - app_dir: FileSystemPathVc, + dir: FileSystemPathVc, page_extensions: StringsVc, ) -> Result { - let DirectoryContent::Entries(entries) = &*app_dir.read_dir().await? else { - bail!("app_dir must be a directory") + let DirectoryContent::Entries(entries) = &*dir.read_dir().await? else { + bail!("{} must be a directory", dir.to_string().await?); }; let page_extensions_value = page_extensions.await?; @@ -451,7 +451,16 @@ async fn merge_loader_trees( } #[derive( - Copy, Clone, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, ValueDebugFormat, Debug, + Copy, + Clone, + PartialEq, + Eq, + Serialize, + Deserialize, + TraceRawVcs, + ValueDebugFormat, + Debug, + TaskInput, )] pub enum Entrypoint { AppPage { loader_tree: LoaderTreeVc }, diff --git a/packages/next-swc/crates/next-core/src/emit.rs b/packages/next-swc/crates/next-core/src/emit.rs new file mode 100644 index 0000000000000..5fc9d94793a2f --- /dev/null +++ b/packages/next-swc/crates/next-core/src/emit.rs @@ -0,0 +1,89 @@ +use anyhow::Result; +use turbo_tasks::{ + graph::{AdjacencyMap, GraphTraversal}, + CompletionVc, CompletionsVc, TryJoinIterExt, +}; +use turbo_tasks_fs::{rebase, FileSystemPathVc}; +use turbopack_binding::turbopack::core::{ + asset::{Asset, AssetVc, AssetsVc}, + reference::AssetReference, +}; + +/// Emits all assets transitively reachable from the given chunks, that are +/// inside the node root or the client root. +#[turbo_tasks::function] +pub async fn emit_all_assets( + assets: AssetsVc, + node_root: FileSystemPathVc, + client_relative_path: FileSystemPathVc, + client_output_path: FileSystemPathVc, +) -> Result { + let all_assets = all_assets_from_entries(assets).await?; + Ok(CompletionsVc::all( + all_assets + .iter() + .copied() + .map(|asset| async move { + if asset.ident().path().await?.is_inside(&*node_root.await?) { + return Ok(emit(asset)); + } else if asset + .ident() + .path() + .await? + .is_inside(&*client_relative_path.await?) + { + // Client assets are emitted to the client output path, which is prefixed with + // _next. We need to rebase them to remove that prefix. + return Ok(emit_rebase(asset, client_relative_path, client_output_path)); + } + + Ok(CompletionVc::immutable()) + }) + .try_join() + .await?, + )) +} + +#[turbo_tasks::function] +fn emit(asset: AssetVc) -> CompletionVc { + asset.content().write(asset.ident().path()) +} + +#[turbo_tasks::function] +fn emit_rebase(asset: AssetVc, from: FileSystemPathVc, to: FileSystemPathVc) -> CompletionVc { + asset + .content() + .write(rebase(asset.ident().path(), from, to)) +} + +/// Walks the asset graph from multiple assets and collect all referenced +/// assets. +#[turbo_tasks::function] +async fn all_assets_from_entries(entries: AssetsVc) -> Result { + Ok(AssetsVc::cell( + AdjacencyMap::new() + .skip_duplicates() + .visit(entries.await?.iter().copied(), get_referenced_assets) + .await + .completed()? + .into_inner() + .into_reverse_topological() + .collect(), + )) +} + +/// Computes the list of all chunk children of a given chunk. +async fn get_referenced_assets(asset: AssetVc) -> Result + Send> { + Ok(asset + .references() + .await? + .iter() + .map(|reference| async move { + let primary_assets = reference.resolve_reference().primary_assets().await?; + Ok(primary_assets.clone_value()) + }) + .try_join() + .await? + .into_iter() + .flatten()) +} diff --git a/packages/next-swc/crates/next-core/src/lib.rs b/packages/next-swc/crates/next-core/src/lib.rs index 1df03990d053a..293e839c46aac 100644 --- a/packages/next-swc/crates/next-core/src/lib.rs +++ b/packages/next-swc/crates/next-core/src/lib.rs @@ -11,6 +11,7 @@ pub mod app_structure; mod babel; mod bootstrap; mod embed_js; +mod emit; pub mod env; mod fallback; pub mod loader_tree; @@ -41,10 +42,11 @@ mod runtime; mod sass; mod transform_options; pub mod url_node; -mod util; +pub mod util; mod web_entry_source; pub use app_source::create_app_source; +pub use emit::emit_all_assets; pub use next_app::unsupported_dynamic_metadata_issue::{ UnsupportedDynamicMetadataIssue, UnsupportedDynamicMetadataIssueVc, }; diff --git a/packages/next-swc/crates/next-core/src/manifest.rs b/packages/next-swc/crates/next-core/src/manifest.rs index 5d414de2b94a1..ce9a76d1ca8ab 100644 --- a/packages/next-swc/crates/next-core/src/manifest.rs +++ b/packages/next-swc/crates/next-core/src/manifest.rs @@ -26,7 +26,7 @@ use turbopack_binding::{ use crate::{ embed_js::next_js_file, - next_config::{NextConfigVc, RewritesReadRef}, + next_config::{RewritesReadRef, RewritesVc}, util::get_asset_path_from_pathname, }; @@ -35,7 +35,7 @@ use crate::{ #[turbo_tasks::value(shared)] pub struct DevManifestContentSource { pub page_roots: Vec, - pub next_config: NextConfigVc, + pub rewrites: RewritesVc, } #[turbo_tasks::value_impl] @@ -124,7 +124,7 @@ impl DevManifestContentSourceVc { .collect(); let manifest = BuildManifest { - rewrites: this.next_config.rewrites().await?, + rewrites: this.rewrites.await?, sorted_pages, routes, }; diff --git a/packages/next-swc/crates/next-core/src/next_config.rs b/packages/next-swc/crates/next-core/src/next_config.rs index b2025d5799b42..f0c61f2aa9751 100644 --- a/packages/next-swc/crates/next-core/src/next_config.rs +++ b/packages/next-swc/crates/next-core/src/next_config.rs @@ -45,6 +45,34 @@ use turbopack_binding::{ use crate::{embed_js::next_asset, next_shared::transforms::ModularizeImportPackageConfig}; +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct NextConfigAndCustomRoutesRaw { + config: NextConfig, + custom_routes: CustomRoutesRaw, +} + +#[turbo_tasks::value] +struct NextConfigAndCustomRoutes { + config: NextConfigVc, + custom_routes: CustomRoutesVc, +} + +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct CustomRoutesRaw { + rewrites: Rewrites, + + // unsupported + headers: Vec
, + redirects: Vec, +} + +#[turbo_tasks::value] +struct CustomRoutes { + rewrites: RewritesVc, +} + #[turbo_tasks::value(serialization = "custom", eq = "manual")] #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -57,7 +85,6 @@ pub struct NextConfig { pub images: ImageConfig, pub page_extensions: Vec, pub react_strict_mode: Option, - pub rewrites: Rewrites, pub transpile_packages: Option>, pub modularize_imports: Option>, sass_options: Option, @@ -84,7 +111,6 @@ pub struct NextConfig { // this is a function in js land generate_build_id: Option, generate_etags: bool, - headers: Vec
, http_agent_options: HttpAgentConfig, i18n: Option, on_demand_entries: OnDemandEntriesConfig, @@ -93,7 +119,6 @@ pub struct NextConfig { powered_by_header: bool, production_browser_source_maps: bool, public_runtime_config: IndexMap, - redirects: Vec, server_runtime_config: IndexMap, static_page_generation_timeout: f64, swc_minify: bool, @@ -486,6 +511,13 @@ pub enum RemoveConsoleConfig { #[turbo_tasks::value_impl] impl NextConfigVc { + #[turbo_tasks::function] + pub fn from_string(s: String) -> Result { + let config: NextConfig = serde_json::from_str(&s) + .with_context(|| format!("failed to parse next.config.js: {}", s))?; + Ok(config.cell()) + } + #[turbo_tasks::function] pub async fn server_component_externals(self) -> Result { Ok(StringsVc::cell( @@ -545,11 +577,6 @@ impl NextConfigVc { Ok(StringsVc::cell(self.await?.page_extensions.clone())) } - #[turbo_tasks::function] - pub async fn rewrites(self) -> Result { - Ok(self.await?.rewrites.clone().cell()) - } - #[turbo_tasks::function] pub async fn transpile_packages(self) -> Result { Ok(StringsVc::cell( @@ -646,22 +673,41 @@ fn next_configs() -> StringsVc { #[turbo_tasks::function] pub async fn load_next_config(execution_context: ExecutionContextVc) -> Result { + Ok(load_config_and_custom_routes(execution_context) + .await? + .config) +} + +#[turbo_tasks::function] +pub async fn load_rewrites(execution_context: ExecutionContextVc) -> Result { + Ok(load_config_and_custom_routes(execution_context) + .await? + .custom_routes + .await? + .rewrites) +} + +#[turbo_tasks::function] +async fn load_config_and_custom_routes( + execution_context: ExecutionContextVc, +) -> Result { let ExecutionContext { project_path, .. } = *execution_context.await?; let find_config_result = find_context_file(project_path, next_configs()); let config_file = match &*find_config_result.await? { FindContextFileResult::Found(config_path, _) => Some(*config_path), FindContextFileResult::NotFound(_) => None, }; - load_next_config_internal(execution_context, config_file) + + load_next_config_and_custom_routes_internal(execution_context, config_file) .issue_context(config_file, "Loading Next.js config") .await } #[turbo_tasks::function] -pub async fn load_next_config_internal( +async fn load_next_config_and_custom_routes_internal( execution_context: ExecutionContextVc, config_file: Option, -) -> Result { +) -> Result { let ExecutionContext { project_path, chunking_context, @@ -709,11 +755,24 @@ pub async fn load_next_config_internal( .await .context("Evaluation of Next.js config failed")? else { - return Ok(NextConfig::default().cell()); + return Ok(NextConfigAndCustomRoutes { + config: NextConfig::default().cell(), + custom_routes: CustomRoutes { + rewrites: Rewrites::default().cell(), + } + .cell(), + } + .cell()); }; - let next_config: NextConfig = parse_json_with_source_context(val.to_str()?)?; - - if let Some(turbo) = next_config.experimental.turbo.as_ref() { + let next_config_and_custom_routes: NextConfigAndCustomRoutesRaw = + parse_json_with_source_context(val.to_str()?)?; + + if let Some(turbo) = next_config_and_custom_routes + .config + .experimental + .turbo + .as_ref() + { if turbo.loaders.is_some() { OutdatedConfigIssue { path: config_file.unwrap_or(project_path), @@ -730,7 +789,14 @@ Example: loaders: { \".mdx\": [\"mdx-loader\"] } -> rules: { \"*.mdx\": [\"mdx-l } } - Ok(next_config.cell()) + Ok(NextConfigAndCustomRoutes { + config: next_config_and_custom_routes.config.cell(), + custom_routes: CustomRoutes { + rewrites: next_config_and_custom_routes.custom_routes.rewrites.cell(), + } + .cell(), + } + .cell()) } #[turbo_tasks::function] diff --git a/packages/next-swc/crates/next-core/src/pages_structure.rs b/packages/next-swc/crates/next-core/src/pages_structure.rs index 22992d5018420..c07aebe16cb25 100644 --- a/packages/next-swc/crates/next-core/src/pages_structure.rs +++ b/packages/next-swc/crates/next-core/src/pages_structure.rs @@ -5,7 +5,7 @@ use turbopack_binding::turbo::tasks_fs::{ DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPathVc, }; -use crate::{embed_js::next_js_file_path, next_config::NextConfigVc}; +use crate::embed_js::next_js_file_path; /// A final route in the pages directory. #[turbo_tasks::value] @@ -125,7 +125,7 @@ impl PagesDirectoryStructureVc { pub async fn find_pages_structure( project_root: FileSystemPathVc, next_router_root: FileSystemPathVc, - next_config: NextConfigVc, + page_extensions: StringsVc, ) -> Result { let pages_root = project_root.join("pages"); let pages_root: FileSystemPathOptionVc = FileSystemPathOptionVc::cell( @@ -149,7 +149,7 @@ pub async fn find_pages_structure( Ok(get_pages_structure_for_root_directory( pages_root, next_router_root, - next_config.page_extensions(), + page_extensions, )) } diff --git a/packages/next-swc/crates/next-dev/src/lib.rs b/packages/next-swc/crates/next-dev/src/lib.rs index aeebc0b274a25..752e6cb685ed8 100644 --- a/packages/next-swc/crates/next-dev/src/lib.rs +++ b/packages/next-swc/crates/next-dev/src/lib.rs @@ -25,7 +25,7 @@ use next_core::{ manifest::DevManifestContentSource, mode::NextMode, next_client::{get_client_chunking_context, get_client_compile_time_info}, - next_config::load_next_config, + next_config::{load_next_config, load_rewrites}, next_image::NextImageContentSourceVc, pages_structure::find_pages_structure, router_source::NextRouterContentSourceVc, @@ -335,7 +335,9 @@ async fn source( ExecutionContextVc::new(project_path, build_chunking_context.into(), env); let mode = NextMode::Development; - let next_config = load_next_config(execution_context.with_layer("next_config")); + let next_config_execution_context = execution_context.with_layer("next_config"); + let next_config = load_next_config(next_config_execution_context); + let rewrites = load_rewrites(next_config_execution_context); let output_root = output_fs.root().join(".next/server"); @@ -367,7 +369,8 @@ async fn source( client_compile_time_info.environment(), mode, ); - let pages_structure = find_pages_structure(project_path, dev_server_root, next_config); + let pages_structure = + find_pages_structure(project_path, dev_server_root, next_config.page_extensions()); let page_source = create_page_source( pages_structure, project_path, @@ -402,7 +405,7 @@ async fn source( StaticAssetsContentSourceVc::new(String::new(), project_path.join("public")).into(); let manifest_source = DevManifestContentSource { page_roots: vec![page_source], - next_config, + rewrites, } .cell() .into(); diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index 4a07fdc06e903..eef3d39f1a237 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -939,7 +939,7 @@ export default async function build( ignore: [] as string[], })) - let binding = (await loadBindings()) as any + let binding = await loadBindings() async function turbopackBuild() { const turboNextBuildStart = process.hrtime() diff --git a/packages/next/src/build/swc/index.ts b/packages/next/src/build/swc/index.ts index c5d5677a264cd..0e4731507d856 100644 --- a/packages/next/src/build/swc/index.ts +++ b/packages/next/src/build/swc/index.ts @@ -9,6 +9,9 @@ import { eventSwcLoadFailure } from '../../telemetry/events/swc-load-failure' import { patchIncorrectLockfile } from '../../lib/patch-incorrect-lockfile' import { downloadWasmSwc } from '../../lib/download-wasm-swc' import { spawn } from 'child_process' +import { NextConfigComplete, TurboLoaderItem } from '../../server/config-shared' +import loadCustomRoutes from '../../lib/load-custom-routes' +import { isDeepStrictEqual } from 'util' const nextVersion = process.env.__NEXT_VERSION as string @@ -88,7 +91,38 @@ let swcHeapProfilerFlushGuard: any let swcCrashReporterFlushGuard: any export const lockfilePatchPromise: { cur?: Promise } = {} -export async function loadBindings(): Promise { +export interface Binding { + isWasm: boolean + turbo: { + startDev: any + startTrace: any + nextBuild?: any + createTurboTasks?: any + entrypoints: { + stream: any + get: any + } + mdx: { + compile: any + compileSync: any + } + createProject: (options: ProjectOptions) => Promise + } + minify: any + minifySync: any + transform: any + transformSync: any + parse: any + parseSync: any + getTargetTriple(): string | undefined + initCustomTraceSubscriber?: any + teardownTraceSubscriber?: any + initHeapProfiler?: any + teardownHeapProfiler?: any + teardownCrashReporter?: any +} + +export async function loadBindings(): Promise { if (pendingBindings) { return pendingBindings } @@ -236,6 +270,383 @@ function logLoadFailure(attempts: any, triedWasm = false) { }) } +interface ProjectOptions { + /** + * A root path from which all files must be nested under. Trying to access + * a file outside this root will fail. Think of this as a chroot. + */ + rootPath: string + + /** + * A path inside the root_path which contains the app/pages directories. + */ + projectPath: string + + /** + * The next.config.js contents. + */ + nextConfig: NextConfigComplete + + /** + * Whether to watch he filesystem for file changes. + */ + watch: boolean + + /** + * An upper bound of memory that turbopack will attempt to stay under. + */ + memoryLimit?: number +} + +interface EntrypointsOptions { + /** File extensions to scan inside our project */ + pageExtensions: string[] +} + +interface Issue {} + +interface Diagnostics {} + +type TurbopackResult = T & { + issues: Issue[] + diagnostics: Diagnostics[] +} + +interface Middleware { + endpoint: Endpoint + runtime: 'nodejs' | 'edge' + matcher?: string[] +} + +interface Entrypoints { + routes: Map + middleware?: Middleware +} + +interface Project { + entrypointsSubscribe(): AsyncIterableIterator> +} + +type Route = + | { + type: 'conflict' + } + | { + type: 'app-page' + htmlEndpoint: Endpoint + rscEndpoint: Endpoint + } + | { + type: 'app-route' + endpoint: Endpoint + } + | { + type: 'page' + htmlEndpoint: Endpoint + dataEndpoint: Endpoint + } + | { + type: 'page-api' + endpoint: Endpoint + } + +interface Endpoint { + /** Write files for the endpoint to disk. */ + writeToDisk(): Promise> + /** + * Listen to changes to the endpoint. + * After changed() has been awaited it will listen to changes. + * The async iterator will yield for each change. + */ + changed(): Promise> +} + +interface EndpointConfig { + dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static' + dynamicParams?: boolean + revalidate?: 'never' | 'force-cache' | number + fetchCache?: + | 'auto' + | 'default-cache' + | 'only-cache' + | 'force-cache' + | 'default-no-store' + | 'only-no-store' + | 'force-no-store' + runtime?: 'nodejs' | 'edge' + preferredRegion?: string +} + +interface WrittenEndpoint { + /** The entry path for the endpoint. */ + entryPath: string + /** All paths that has been written for the endpoint. */ + paths: string[] + config: EndpointConfig +} + +function bindingToApi(binding: any, wasm: boolean) { + type NativeFunction = ( + callback: (err: Error, value: T) => void + ) => Promise<{ __napiType: 'RootTask' }> + + /** + * Utility function to ensure all variants of an enum are handled. + */ + function invariant( + never: never, + computeMessage: (arg: any) => string + ): never { + throw new Error(`Invariant: ${computeMessage(never)}`) + } + + /** + * Calls a native function and streams the result. + * If useBuffer is true, all values will be preserved, potentially buffered + * if consumed slower than produced. Else, only the latest value will be + * preserved. + */ + function subscribe( + useBuffer: boolean, + nativeFunction: NativeFunction + ): AsyncIterableIterator { + type BufferItem = + | { err: Error; value: undefined } + | { err: undefined; value: T } + // A buffer of produced items. This will only contain values if the + // consumer is slower than the producer. + let buffer: BufferItem[] = [] + // A deferred value waiting for the next produced item. This will only + // exist if the consumer is faster than the producer. + let waiting: + | { + resolve: (value: T) => void + reject: (error: Error) => void + } + | undefined + + // The native function will call this every time it emits a new result. We + // either need to notify a waiting consumer, or buffer the new result until + // the consumer catches up. + const emitResult = (err: Error | undefined, value: T | undefined) => { + if (waiting) { + let { resolve, reject } = waiting + waiting = undefined + if (err) reject(err) + else resolve(value!) + } else { + const item = { err, value } as BufferItem + if (useBuffer) buffer.push(item) + else buffer[0] = item + } + } + + return (async function* () { + const task = await nativeFunction(emitResult) + try { + while (true) { + if (buffer.length > 0) { + const item = buffer.shift()! + if (item.err) throw item.err + yield item.value + } else { + // eslint-disable-next-line no-loop-func + yield new Promise((resolve, reject) => { + waiting = { resolve, reject } + }) + } + } + } finally { + binding.rootTaskDispose(task) + } + })() + } + + class ProjectImpl implements Project { + private _nativeProject: { __napiType: 'Project' } + + constructor(nativeProject: { __napiType: 'Project' }) { + this._nativeProject = nativeProject + } + + entrypointsSubscribe() { + type NapiEndpoint = { __napiType: 'Endpoint' } + + type NapiEntrypoints = { + routes: NapiRoute[] + middleware?: NapiMiddleware + issues: Issue[] + diagnostics: Diagnostics[] + } + + type NapiMiddleware = { + endpoint: NapiEndpoint + runtime: 'nodejs' | 'edge' + matcher?: string[] + } + + type NapiRoute = { + pathname: string + } & ( + | { + type: 'page' + htmlEndpoint: NapiEndpoint + dataEndpoint: NapiEndpoint + } + | { + type: 'page-api' + endpoint: NapiEndpoint + } + | { + type: 'app-page' + htmlEndpoint: NapiEndpoint + rscEndpoint: NapiEndpoint + } + | { + type: 'app-route' + endpoint: NapiEndpoint + } + | { + type: 'conflict' + } + ) + + const subscription = subscribe(false, async (callback) => + binding.projectEntrypointsSubscribe(await this._nativeProject, callback) + ) + return (async function* () { + for await (const entrypoints of subscription) { + const routes = new Map() + for (const { pathname, ...nativeRoute } of entrypoints.routes) { + let route: Route + switch (nativeRoute.type) { + case 'page': + route = { + type: 'page', + htmlEndpoint: new EndpointImpl(nativeRoute.htmlEndpoint), + dataEndpoint: new EndpointImpl(nativeRoute.dataEndpoint), + } + break + case 'page-api': + route = { + type: 'page-api', + endpoint: new EndpointImpl(nativeRoute.endpoint), + } + break + case 'app-page': + route = { + type: 'app-page', + htmlEndpoint: new EndpointImpl(nativeRoute.htmlEndpoint), + rscEndpoint: new EndpointImpl(nativeRoute.rscEndpoint), + } + break + case 'app-route': + route = { + type: 'app-route', + endpoint: new EndpointImpl(nativeRoute.endpoint), + } + break + case 'conflict': + route = { + type: 'conflict', + } + break + default: + invariant( + nativeRoute, + () => `Unknown route type: ${(nativeRoute as any).type}` + ) + break + } + routes.set(pathname, route) + } + const napiMiddlewareToMiddleware = (middleware: NapiMiddleware) => ({ + endpoint: new EndpointImpl(middleware.endpoint), + runtime: middleware.runtime, + matcher: middleware.matcher, + }) + const middleware = entrypoints.middleware + ? napiMiddlewareToMiddleware(entrypoints.middleware) + : undefined + yield { + routes, + middleware, + issues: entrypoints.issues, + diagnostics: entrypoints.diagnostics, + } + } + })() + } + } + + class EndpointImpl implements Endpoint { + private _nativeEndpoint: { __napiType: 'Endpoint' } + + constructor(nativeEndpoint: { __napiType: 'Endpoint' }) { + this._nativeEndpoint = nativeEndpoint + } + + async writeToDisk(): Promise> { + return await binding.endpointWriteToDisk(this._nativeEndpoint) + } + + async changed(): Promise> { + const iter = subscribe(false, async (callback) => + binding.endpointChangedSubscribe(await this._nativeEndpoint, callback) + ) + await iter.next() + return iter + } + } + + async function serializeNextConfig( + nextConfig: NextConfigComplete + ): Promise { + let nextConfigSerializable = nextConfig as any + + nextConfigSerializable.generateBuildId = + await nextConfig.generateBuildId?.() + + // TODO: these functions takes arguments, have to be supported in a different way + nextConfigSerializable.exportPathMap = {} + nextConfigSerializable.webpack = nextConfig.webpack && {} + + if (nextConfig.experimental?.turbo?.loaders) { + ensureLoadersHaveSerializableOptions( + nextConfig.experimental.turbo.loaders + ) + } + + return JSON.stringify(nextConfigSerializable) + } + + function ensureLoadersHaveSerializableOptions( + turbopackLoaders: Record + ) { + for (const [ext, loaderItems] of Object.entries(turbopackLoaders)) { + for (const loaderItem of loaderItems) { + if ( + typeof loaderItem !== 'string' && + !isDeepStrictEqual(loaderItem, JSON.parse(JSON.stringify(loaderItem))) + ) { + throw new Error( + `loader ${loaderItem.loader} for match "${ext}" does not have serializable options. Ensure that options passed are plain JavaScript objects and values.` + ) + } + } + } + } + + async function createProject(options: ProjectOptions) { + const optionsForRust = options as any + optionsForRust.nextConfig = await serializeNextConfig(options.nextConfig) + + return new ProjectImpl(await binding.projectNew(optionsForRust)) + } + + return createProject +} + async function loadWasm(importPath = '', isCustomTurbopack: boolean) { if (wasmBindings) { return wasmBindings @@ -314,9 +725,6 @@ async function loadWasm(importPath = '', isCustomTurbopack: boolean) { startTrace: () => { Log.error('Wasm binding does not support trace yet') }, - experimentalTurbo: () => { - Log.error('Wasm binding does not support this interface') - }, entrypoints: { stream: ( turboTasks: any, @@ -577,12 +985,6 @@ function loadNative(isCustomTurbopack = false) { ) return ret }, - experimentalTurbo: () => { - initHeapProfiler() - - const ret = bindings.experimentalTurbo() - return ret - }, createTurboTasks: (memoryLimit?: number): unknown => bindings.createTurboTasks(memoryLimit), entrypoints: { @@ -615,6 +1017,7 @@ function loadNative(isCustomTurbopack = false) { ) }, }, + createProject: bindingToApi(bindings, false), }, mdx: { compile: (src: string, options: any) => diff --git a/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts b/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts index 8627ee17f00bd..7c4a7a72205c7 100644 --- a/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts +++ b/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts @@ -218,7 +218,7 @@ export class TraceEntryPointsPlugin implements webpack.WebpackPluginInstance { // startTrace existed and callable if (this.turbotrace) { - let binding = (await loadBindings()) as any + let binding = await loadBindings() if ( !binding?.isWasm && typeof binding.turbo.startTrace === 'function' @@ -475,7 +475,7 @@ export class TraceEntryPointsPlugin implements webpack.WebpackPluginInstance { }) // startTrace existed and callable if (this.turbotrace) { - let binding = (await loadBindings()) as any + let binding = await loadBindings() if ( !binding?.isWasm && typeof binding.turbo.startTrace === 'function' @@ -825,7 +825,7 @@ export class TraceEntryPointsPlugin implements webpack.WebpackPluginInstance { if (this.turbotrace) { compiler.hooks.afterEmit.tapPromise(PLUGIN_NAME, async () => { - let binding = (await loadBindings()) as any + let binding = await loadBindings() if ( !binding?.isWasm && typeof binding.turbo.startTrace === 'function' diff --git a/packages/next/src/cli/next-dev.ts b/packages/next/src/cli/next-dev.ts index ff1654fd364dd..65102a0f91530 100644 --- a/packages/next/src/cli/next-dev.ts +++ b/packages/next/src/cli/next-dev.ts @@ -211,7 +211,6 @@ const nextDev: CliCommand = async (argv) => { // We do not set a default host value here to prevent breaking // some set-ups that rely on listening on other interfaces const host = args['--hostname'] - const experimentalTurbo = args['--experimental-turbo'] const devServerOptions: StartServerOptions = { dir, @@ -221,14 +220,62 @@ const nextDev: CliCommand = async (argv) => { hostname: host, // This is required especially for app dir. useWorkers: true, - isExperimentalTurbo: experimentalTurbo, } if (args['--turbo']) { process.env.TURBOPACK = '1' } + if (args['--experimental-turbo']) { + process.env.EXPERIMENTAL_TURBOPACK = '1' + } + const experimentalTurbo = !!process.env.EXPERIMENTAL_TURBOPACK + + if (experimentalTurbo) { + const { loadBindings, __isCustomTurbopackBinary, teardownHeapProfiler } = + require('../build/swc') as typeof import('../build/swc') - if (process.env.TURBOPACK) { + resetEnv() + let bindings = await loadBindings() + + // TODO(alexkirsz) Do we still need the `rawConfig` above? + const config = await loadConfig( + PHASE_DEVELOPMENT_SERVER, + dir, + undefined, + undefined, + true + ) + + // Just testing code here: + + const project = await bindings.turbo.createProject({ + projectPath: dir, + rootPath: dir, + nextConfig: config, + watch: true, + }) + const iter = project.entrypointsSubscribe() + + try { + for await (const entrypoints of iter) { + for (const [pathname, route] of entrypoints.routes) { + switch (route.type) { + case 'page': { + console.log(`writing ${pathname} to disk`) + const written = await route.htmlEndpoint.writeToDisk() + console.log(written) + break + } + } + } + } + } catch (e) { + console.error(e) + } + + Log.error('Not supported yet') + process.exit(1) + } else if (process.env.TURBOPACK) { isTurboSession = true const { validateTurboNextConfig } = @@ -297,7 +344,8 @@ const nextDev: CliCommand = async (argv) => { // Turbopack need to be in control over reading the .env files and watching them. // So we need to start with a initial env to know which env vars are coming from the user. resetEnv() - let bindings: any = await loadBindings() + let bindings = await loadBindings() + let server = bindings.turbo.startDev({ ...devServerOptions, showAll: args['--show-all'] ?? false, @@ -318,11 +366,6 @@ const nextDev: CliCommand = async (argv) => { return server } else { - if (experimentalTurbo) { - Log.error('Not supported yet') - process.exit(1) - } - let cleanupFns: (() => Promise | void)[] = [] const runDevServer = async () => { const oldCleanupFns = cleanupFns diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index 45f0e419e5101..4d96f8ba4e710 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -85,7 +85,7 @@ type JSONValue = | JSONValue[] | { [k: string]: JSONValue } -type TurboLoaderItem = +export type TurboLoaderItem = | string | { loader: string @@ -93,7 +93,7 @@ type TurboLoaderItem = options: Record } -interface ExperimentalTurboOptions { +export interface ExperimentalTurboOptions { /** * (`next --turbo` only) A mapping of aliased imports to modules to load in their place. * diff --git a/packages/next/src/server/lib/start-server.ts b/packages/next/src/server/lib/start-server.ts index e10a34e1fb649..50fa905a53ad3 100644 --- a/packages/next/src/server/lib/start-server.ts +++ b/packages/next/src/server/lib/start-server.ts @@ -22,7 +22,6 @@ export interface StartServerOptions { useWorkers: boolean allowRetry?: boolean isTurbopack?: boolean - isExperimentalTurbo?: boolean keepAliveTimeout?: number onStdout?: (data: any) => void onStderr?: (data: any) => void From 78926e4958dd8156354a1fe275b8c6e0e75def65 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 13 Jul 2023 14:47:32 +0200 Subject: [PATCH 2/9] Missing source method --- packages/next-swc/crates/next-api/src/pages.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/next-swc/crates/next-api/src/pages.rs b/packages/next-swc/crates/next-api/src/pages.rs index 066d704ef9665..ac3368088b65a 100644 --- a/packages/next-swc/crates/next-api/src/pages.rs +++ b/packages/next-swc/crates/next-api/src/pages.rs @@ -254,6 +254,12 @@ impl PageDataEndpointVc { .cell() } + #[turbo_tasks::function] + async fn source(self) -> Result { + let this = self.await?; + Ok(FileSourceVc::new(this.path).into()) + } + #[turbo_tasks::function] async fn ssr_data_chunk(self) -> Result { let this = self.await?; From 260b8104268c4c3acafc10f4ff3315def6c6b938 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 13 Jul 2023 15:18:53 +0200 Subject: [PATCH 3/9] Output asset rebase fix --- .../next-swc/crates/next-api/src/pages.rs | 21 ++++++++++--------- .../next-swc/crates/next-core/src/emit.rs | 20 +++++++++++------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/packages/next-swc/crates/next-api/src/pages.rs b/packages/next-swc/crates/next-api/src/pages.rs index ac3368088b65a..3d1419022ed7f 100644 --- a/packages/next-swc/crates/next-api/src/pages.rs +++ b/packages/next-swc/crates/next-api/src/pages.rs @@ -12,11 +12,12 @@ use turbopack_binding::{ turbo::tasks_fs::FileSystemPathVc, turbopack::{ core::{ - asset::{Asset, AssetVc, AssetsVc}, - changed::{any_content_changed, any_content_changed_of_assets}, + asset::Asset, + changed::{any_content_changed, any_content_changed_of_output_assets}, chunk::{ChunkableModule, ChunkingContext}, context::AssetContext, file_source::FileSourceVc, + output::{OutputAssetVc, OutputAssetsVc}, reference_type::{EntryReferenceSubType, ReferenceType}, source::SourceVc, }, @@ -127,7 +128,7 @@ impl PageHtmlEndpointVc { } #[turbo_tasks::function] - async fn client_chunks(self) -> Result { + async fn client_chunks(self) -> Result { let this = self.await?; let client_module = create_page_loader_entry_module( @@ -156,7 +157,7 @@ impl PageHtmlEndpointVc { } #[turbo_tasks::function] - async fn ssr_chunk(self) -> Result { + async fn ssr_chunk(self) -> Result { let this = self.await?; let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page)); @@ -190,7 +191,7 @@ impl Endpoint for PageHtmlEndpoint { let this = self_vc.await?; let ssr_chunk = self_vc.ssr_chunk(); let ssr_emit = emit_all_assets( - AssetsVc::cell(vec![ssr_chunk]), + OutputAssetsVc::cell(vec![ssr_chunk]), this.project.node_root(), this.project.client_root().join("_next"), this.project.node_root(), @@ -222,8 +223,8 @@ impl Endpoint for PageHtmlEndpoint { fn changed(self_vc: PageHtmlEndpointVc) -> CompletionVc { let ssr_chunk = self_vc.ssr_chunk(); CompletionsVc::all(vec![ - any_content_changed(ssr_chunk), - any_content_changed_of_assets(self_vc.client_chunks()), + any_content_changed(ssr_chunk.into()), + any_content_changed_of_output_assets(self_vc.client_chunks()), ]) } } @@ -261,7 +262,7 @@ impl PageDataEndpointVc { } #[turbo_tasks::function] - async fn ssr_data_chunk(self) -> Result { + async fn ssr_data_chunk(self) -> Result { let this = self.await?; let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page)); @@ -299,7 +300,7 @@ impl Endpoint for PageDataEndpoint { let this = self_vc.await?; let ssr_data_chunk = self_vc.ssr_data_chunk(); emit_all_assets( - AssetsVc::cell(vec![ssr_data_chunk]), + OutputAssetsVc::cell(vec![ssr_data_chunk.into()]), this.project.node_root(), this.project.client_root().join("_next"), this.project.node_root(), @@ -322,7 +323,7 @@ impl Endpoint for PageDataEndpoint { #[turbo_tasks::function] async fn changed(self_vc: PageDataEndpointVc) -> Result { let ssr_data_chunk = self_vc.ssr_data_chunk(); - Ok(any_content_changed(ssr_data_chunk)) + Ok(any_content_changed(ssr_data_chunk.into())) } } diff --git a/packages/next-swc/crates/next-core/src/emit.rs b/packages/next-swc/crates/next-core/src/emit.rs index 5fc9d94793a2f..b6eef2d7fd3ce 100644 --- a/packages/next-swc/crates/next-core/src/emit.rs +++ b/packages/next-swc/crates/next-core/src/emit.rs @@ -5,7 +5,8 @@ use turbo_tasks::{ }; use turbo_tasks_fs::{rebase, FileSystemPathVc}; use turbopack_binding::turbopack::core::{ - asset::{Asset, AssetVc, AssetsVc}, + asset::Asset, + output::{asset_to_output_asset, OutputAssetVc, OutputAssetsVc}, reference::AssetReference, }; @@ -13,7 +14,7 @@ use turbopack_binding::turbopack::core::{ /// inside the node root or the client root. #[turbo_tasks::function] pub async fn emit_all_assets( - assets: AssetsVc, + assets: OutputAssetsVc, node_root: FileSystemPathVc, client_relative_path: FileSystemPathVc, client_output_path: FileSystemPathVc, @@ -45,12 +46,12 @@ pub async fn emit_all_assets( } #[turbo_tasks::function] -fn emit(asset: AssetVc) -> CompletionVc { +fn emit(asset: OutputAssetVc) -> CompletionVc { asset.content().write(asset.ident().path()) } #[turbo_tasks::function] -fn emit_rebase(asset: AssetVc, from: FileSystemPathVc, to: FileSystemPathVc) -> CompletionVc { +fn emit_rebase(asset: OutputAssetVc, from: FileSystemPathVc, to: FileSystemPathVc) -> CompletionVc { asset .content() .write(rebase(asset.ident().path(), from, to)) @@ -59,8 +60,8 @@ fn emit_rebase(asset: AssetVc, from: FileSystemPathVc, to: FileSystemPathVc) -> /// Walks the asset graph from multiple assets and collect all referenced /// assets. #[turbo_tasks::function] -async fn all_assets_from_entries(entries: AssetsVc) -> Result { - Ok(AssetsVc::cell( +async fn all_assets_from_entries(entries: OutputAssetsVc) -> Result { + Ok(OutputAssetsVc::cell( AdjacencyMap::new() .skip_duplicates() .visit(entries.await?.iter().copied(), get_referenced_assets) @@ -73,7 +74,9 @@ async fn all_assets_from_entries(entries: AssetsVc) -> Result { } /// Computes the list of all chunk children of a given chunk. -async fn get_referenced_assets(asset: AssetVc) -> Result + Send> { +async fn get_referenced_assets( + asset: OutputAssetVc, +) -> Result + Send> { Ok(asset .references() .await? @@ -85,5 +88,6 @@ async fn get_referenced_assets(asset: AssetVc) -> Result Date: Thu, 13 Jul 2023 15:23:19 +0200 Subject: [PATCH 4/9] Link --- Cargo.lock | 70 +++++++++---------- Cargo.toml | 6 +- .../next-swc/crates/next-core/js/package.json | 4 +- pnpm-lock.yaml | 18 ++--- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f129441260848..68359ef994d9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -412,7 +412,7 @@ dependencies = [ [[package]] name = "auto-hash-map" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "serde", ] @@ -3599,7 +3599,7 @@ dependencies = [ [[package]] name = "node-file-trace" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "serde", @@ -7259,7 +7259,7 @@ dependencies = [ [[package]] name = "turbo-tasks" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "auto-hash-map", @@ -7290,7 +7290,7 @@ dependencies = [ [[package]] name = "turbo-tasks-build" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "cargo-lock", @@ -7302,7 +7302,7 @@ dependencies = [ [[package]] name = "turbo-tasks-bytes" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "bytes", @@ -7317,7 +7317,7 @@ dependencies = [ [[package]] name = "turbo-tasks-env" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "dotenvs", @@ -7331,7 +7331,7 @@ dependencies = [ [[package]] name = "turbo-tasks-fetch" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "indexmap", @@ -7348,7 +7348,7 @@ dependencies = [ [[package]] name = "turbo-tasks-fs" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "auto-hash-map", @@ -7378,7 +7378,7 @@ dependencies = [ [[package]] name = "turbo-tasks-hash" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "base16", "hex", @@ -7390,7 +7390,7 @@ dependencies = [ [[package]] name = "turbo-tasks-macros" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "convert_case 0.6.0", @@ -7404,7 +7404,7 @@ dependencies = [ [[package]] name = "turbo-tasks-macros-shared" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "proc-macro2", "quote", @@ -7414,7 +7414,7 @@ dependencies = [ [[package]] name = "turbo-tasks-malloc" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "mimalloc", ] @@ -7422,7 +7422,7 @@ dependencies = [ [[package]] name = "turbo-tasks-memory" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "auto-hash-map", @@ -7445,7 +7445,7 @@ dependencies = [ [[package]] name = "turbo-tasks-testing" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "auto-hash-map", @@ -7458,7 +7458,7 @@ dependencies = [ [[package]] name = "turbopack" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "async-recursion", @@ -7488,7 +7488,7 @@ dependencies = [ [[package]] name = "turbopack-bench" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "chromiumoxide", @@ -7518,7 +7518,7 @@ dependencies = [ [[package]] name = "turbopack-binding" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "auto-hash-map", "mdxjs", @@ -7560,7 +7560,7 @@ dependencies = [ [[package]] name = "turbopack-build" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "indexmap", @@ -7580,7 +7580,7 @@ dependencies = [ [[package]] name = "turbopack-cli-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "clap 4.1.11", @@ -7604,7 +7604,7 @@ dependencies = [ [[package]] name = "turbopack-core" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "async-trait", @@ -7632,7 +7632,7 @@ dependencies = [ [[package]] name = "turbopack-create-test-app" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "clap 4.1.11", @@ -7645,7 +7645,7 @@ dependencies = [ [[package]] name = "turbopack-css" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "async-trait", @@ -7667,7 +7667,7 @@ dependencies = [ [[package]] name = "turbopack-dev" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "indexmap", @@ -7691,7 +7691,7 @@ dependencies = [ [[package]] name = "turbopack-dev-server" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "async-compression", @@ -7727,7 +7727,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "async-trait", @@ -7760,7 +7760,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript-plugins" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "async-trait", @@ -7783,7 +7783,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript-runtime" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "indoc", @@ -7800,7 +7800,7 @@ dependencies = [ [[package]] name = "turbopack-env" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "indexmap", @@ -7816,7 +7816,7 @@ dependencies = [ [[package]] name = "turbopack-image" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "base64 0.21.0", @@ -7836,7 +7836,7 @@ dependencies = [ [[package]] name = "turbopack-json" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "serde", @@ -7851,7 +7851,7 @@ dependencies = [ [[package]] name = "turbopack-mdx" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "mdxjs", @@ -7866,7 +7866,7 @@ dependencies = [ [[package]] name = "turbopack-node" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "async-stream", @@ -7901,7 +7901,7 @@ dependencies = [ [[package]] name = "turbopack-static" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "serde", @@ -7917,7 +7917,7 @@ dependencies = [ [[package]] name = "turbopack-swc-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "swc_core", "turbo-tasks", @@ -7928,7 +7928,7 @@ dependencies = [ [[package]] name = "turbopack-test-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.2#4022f2b0e5bf6183b813f3ff32267d24f058cc82" +source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" dependencies = [ "anyhow", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index ca53f1481e2b2..87403c24ef618 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,11 +44,11 @@ swc_core = { version = "0.79.13" } testing = { version = "0.33.20" } # Turbo crates -turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230713.2" } +turbopack-binding = { git = "https://github.com/vercel/turbo.git", branch = "sokra-alex/next-api" } # last tag: "turbopack-230713.2" # [TODO]: need to refactor embed_directory! macro usages, as well as resolving turbo_tasks::function, macros.. -turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230713.2" } +turbo-tasks = { git = "https://github.com/vercel/turbo.git", branch = "sokra-alex/next-api" } # last tag: "turbopack-230713.2" # [TODO]: need to refactor embed_directory! macro usage in next-core -turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230713.2" } +turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", branch = "sokra-alex/next-api" } # last tag: "turbopack-230713.2" # General Deps diff --git a/packages/next-swc/crates/next-core/js/package.json b/packages/next-swc/crates/next-core/js/package.json index 040040403533b..efb6441cb911e 100644 --- a/packages/next-swc/crates/next-core/js/package.json +++ b/packages/next-swc/crates/next-core/js/package.json @@ -10,8 +10,8 @@ "check": "tsc --noEmit" }, "dependencies": { - "@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.2", - "@vercel/turbopack-node": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230713.2", + "@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5", + "@vercel/turbopack-node": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5", "anser": "^2.1.1", "css.escape": "^1.5.1", "next": "*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f972cca90e668..3ebceea7857b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -992,8 +992,8 @@ importers: '@types/react': 18.2.7 '@types/react-dom': 18.2.4 '@vercel/ncc': ^0.36.0 - '@vercel/turbopack-ecmascript-runtime': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.2 - '@vercel/turbopack-node': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230713.2 + '@vercel/turbopack-ecmascript-runtime': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5 + '@vercel/turbopack-node': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5 anser: ^2.1.1 css.escape: ^1.5.1 find-up: ^6.3.0 @@ -1005,8 +1005,8 @@ importers: stacktrace-parser: ^0.1.10 strip-ansi: ^7.0.1 dependencies: - '@vercel/turbopack-ecmascript-runtime': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.2_react-refresh@0.12.0' - '@vercel/turbopack-node': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230713.2' + '@vercel/turbopack-ecmascript-runtime': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5_react-refresh@0.12.0' + '@vercel/turbopack-node': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5' anser: 2.1.1 css.escape: 1.5.1 next: link:../../../../next @@ -25498,9 +25498,9 @@ packages: /zwitch/2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.2_react-refresh@0.12.0': - resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.2} - id: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.2' + '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5_react-refresh@0.12.0': + resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5} + id: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5' name: '@vercel/turbopack-ecmascript-runtime' version: 0.0.0 dependencies: @@ -25511,8 +25511,8 @@ packages: - webpack dev: false - '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230713.2': - resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230713.2} + '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5': + resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5} name: '@vercel/turbopack-node' version: 0.0.0 dependencies: From 95cebffa5e2faf15526a8d02cb1bd5624d055f9a Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 13 Jul 2023 15:28:32 +0200 Subject: [PATCH 5/9] Lints and fixes --- .../crates/napi/src/next_api/endpoint.rs | 2 +- .../crates/napi/src/next_api/project.rs | 34 +++++++++---------- .../crates/napi/src/next_api/utils.rs | 4 ++- .../next-swc/crates/next-api/src/pages.rs | 11 ++---- .../next-swc/crates/next-api/src/project.rs | 2 +- 5 files changed, 25 insertions(+), 28 deletions(-) diff --git a/packages/next-swc/crates/napi/src/next_api/endpoint.rs b/packages/next-swc/crates/napi/src/next_api/endpoint.rs index 8aef6b3efff3e..da10ebf0121dd 100644 --- a/packages/next-swc/crates/napi/src/next_api/endpoint.rs +++ b/packages/next-swc/crates/napi/src/next_api/endpoint.rs @@ -29,7 +29,7 @@ pub async fn endpoint_write_to_disk( let turbo_tasks = endpoint.turbo_tasks().clone(); let endpoint = **endpoint; let written = turbo_tasks - .run_once(async move { Ok(endpoint.write_to_disk().strongly_consistent().await?) }) + .run_once(endpoint.write_to_disk().strongly_consistent()) .await?; // TODO peek_issues and diagnostics Ok((&*written).into()) diff --git a/packages/next-swc/crates/napi/src/next_api/project.rs b/packages/next-swc/crates/napi/src/next_api/project.rs index d03c69f355701..8a4a91d07f689 100644 --- a/packages/next-swc/crates/napi/src/next_api/project.rs +++ b/packages/next-swc/crates/napi/src/next_api/project.rs @@ -9,7 +9,7 @@ use next_api::{ use turbo_tasks::TurboTasks; use turbopack_binding::turbo::tasks_memory::MemoryBackend; -use super::utils::{serde_enum_to_string, subscribe, RootTask, VcArc}; +use super::utils::{serde_enum_to_string, subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc}; use crate::register; #[napi(object)] @@ -31,14 +31,14 @@ pub struct NapiProjectOptions { pub memory_limit: Option, } -impl Into for NapiProjectOptions { - fn into(self) -> ProjectOptions { +impl From for ProjectOptions { + fn from(val: NapiProjectOptions) -> Self { ProjectOptions { - root_path: self.root_path, - project_path: self.project_path, - watch: self.watch, - next_config: self.next_config, - memory_limit: self.memory_limit.map(|m| m as _), + root_path: val.root_path, + project_path: val.project_path, + watch: val.watch, + next_config: val.next_config, + memory_limit: val.memory_limit.map(|m| m as _), } } } @@ -54,7 +54,7 @@ pub async fn project_new(options: NapiProjectOptions) -> napi::Result NapiRoute { pathname, r#type: "page", - html_endpoint: convert_endpoint(html_endpoint.clone()), - data_endpoint: convert_endpoint(data_endpoint.clone()), + html_endpoint: convert_endpoint(html_endpoint), + data_endpoint: convert_endpoint(data_endpoint), ..Default::default() }, Route::PageApi { endpoint } => NapiRoute { pathname, r#type: "page-api", - endpoint: convert_endpoint(endpoint.clone()), + endpoint: convert_endpoint(endpoint), ..Default::default() }, Route::AppPage { @@ -109,14 +109,14 @@ impl NapiRoute { } => NapiRoute { pathname, r#type: "app-page", - html_endpoint: convert_endpoint(html_endpoint.clone()), - rsc_endpoint: convert_endpoint(rsc_endpoint.clone()), + html_endpoint: convert_endpoint(html_endpoint), + rsc_endpoint: convert_endpoint(rsc_endpoint), ..Default::default() }, Route::AppRoute { endpoint } => NapiRoute { pathname, r#type: "app-route", - endpoint: convert_endpoint(endpoint.clone()), + endpoint: convert_endpoint(endpoint), ..Default::default() }, Route::Conflict => NapiRoute { @@ -141,7 +141,7 @@ impl NapiMiddleware { turbo_tasks: &Arc>, ) -> Result { Ok(NapiMiddleware { - endpoint: External::new(VcArc::new(turbo_tasks.clone(), value.endpoint.clone())), + endpoint: External::new(VcArc::new(turbo_tasks.clone(), value.endpoint)), runtime: serde_enum_to_string(&value.config.runtime)?, matcher: value.config.matcher.clone(), }) @@ -185,7 +185,7 @@ pub fn project_entrypoints_subscribe( middleware: entrypoints .middleware .as_ref() - .map(|m| NapiMiddleware::from_middleware(&m, &turbo_tasks)) + .map(|m| NapiMiddleware::from_middleware(m, &turbo_tasks)) .transpose()?, issues: vec![], diagnostics: vec![], diff --git a/packages/next-swc/crates/napi/src/next_api/utils.rs b/packages/next-swc/crates/napi/src/next_api/utils.rs index fa59e0d8e8ec1..1896c94451dfd 100644 --- a/packages/next-swc/crates/napi/src/next_api/utils.rs +++ b/packages/next-swc/crates/napi/src/next_api/utils.rs @@ -1,6 +1,6 @@ use std::{future::Future, ops::Deref, sync::Arc}; -use anyhow::{anyhow, bail, Context, Result}; +use anyhow::{anyhow, Context, Result}; use napi::{ bindgen_prelude::{External, ToNapiValue}, threadsafe_function::{ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode}, @@ -49,7 +49,9 @@ pub fn serde_enum_to_string(value: &T) -> Result { /// The root of our turbopack computation. pub struct RootTask { + #[allow(dead_code)] turbo_tasks: Arc>, + #[allow(dead_code)] task_id: Option, } diff --git a/packages/next-swc/crates/next-api/src/pages.rs b/packages/next-swc/crates/next-api/src/pages.rs index 3d1419022ed7f..faa5184d7d9a8 100644 --- a/packages/next-swc/crates/next-api/src/pages.rs +++ b/packages/next-swc/crates/next-api/src/pages.rs @@ -79,13 +79,8 @@ pub async fn get_pages_routes( if let Some(page) = pages { add_dir_to_routes(&mut routes, page, |pathname, original_name, path| { Route::Page { - html_endpoint: PageHtmlEndpointVc::new( - project, - pathname.clone(), - original_name.clone(), - path, - ) - .into(), + html_endpoint: PageHtmlEndpointVc::new(project, pathname, original_name, path) + .into(), data_endpoint: PageDataEndpointVc::new(project, pathname, original_name, path) .into(), } @@ -300,7 +295,7 @@ impl Endpoint for PageDataEndpoint { let this = self_vc.await?; let ssr_data_chunk = self_vc.ssr_data_chunk(); emit_all_assets( - OutputAssetsVc::cell(vec![ssr_data_chunk.into()]), + OutputAssetsVc::cell(vec![ssr_data_chunk]), this.project.node_root(), this.project.client_root().join("_next"), this.project.node_root(), diff --git a/packages/next-swc/crates/next-api/src/project.rs b/packages/next-swc/crates/next-api/src/project.rs index 67cbf9c536cbb..4f9b28ba5e41a 100644 --- a/packages/next-swc/crates/next-api/src/project.rs +++ b/packages/next-swc/crates/next-api/src/project.rs @@ -151,7 +151,7 @@ impl ProjectVc { } #[turbo_tasks::function] - async fn node_fs(self) -> Result { + async fn node_fs(self) -> Result { let this = self.await?; let disk_fs = DiskFileSystemVc::new("node".to_string(), this.project_path.clone()); disk_fs.await?.start_watching_with_invalidation_reason()?; From f962387c263b2fceb973bae7f161fcd9fc307ad0 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 13 Jul 2023 15:54:37 +0200 Subject: [PATCH 6/9] Lints --- packages/next/src/build/swc/index.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/next/src/build/swc/index.ts b/packages/next/src/build/swc/index.ts index 0e4731507d856..50671260ddf4c 100644 --- a/packages/next/src/build/swc/index.ts +++ b/packages/next/src/build/swc/index.ts @@ -10,7 +10,6 @@ import { patchIncorrectLockfile } from '../../lib/patch-incorrect-lockfile' import { downloadWasmSwc } from '../../lib/download-wasm-swc' import { spawn } from 'child_process' import { NextConfigComplete, TurboLoaderItem } from '../../server/config-shared' -import loadCustomRoutes from '../../lib/load-custom-routes' import { isDeepStrictEqual } from 'util' const nextVersion = process.env.__NEXT_VERSION as string @@ -298,11 +297,6 @@ interface ProjectOptions { memoryLimit?: number } -interface EntrypointsOptions { - /** File extensions to scan inside our project */ - pageExtensions: string[] -} - interface Issue {} interface Diagnostics {} @@ -385,7 +379,8 @@ interface WrittenEndpoint { config: EndpointConfig } -function bindingToApi(binding: any, wasm: boolean) { +// TODO(sokra) Support wasm option. +function bindingToApi(binding: any, _wasm: boolean) { type NativeFunction = ( callback: (err: Error, value: T) => void ) => Promise<{ __napiType: 'RootTask' }> From 75b8c9c59b2c8e4c9ac705245372482193591042 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 13 Jul 2023 16:04:17 +0200 Subject: [PATCH 7/9] Lints --- packages/next/src/cli/next-dev.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/next/src/cli/next-dev.ts b/packages/next/src/cli/next-dev.ts index 65102a0f91530..3c787385eaaa9 100644 --- a/packages/next/src/cli/next-dev.ts +++ b/packages/next/src/cli/next-dev.ts @@ -231,13 +231,12 @@ const nextDev: CliCommand = async (argv) => { const experimentalTurbo = !!process.env.EXPERIMENTAL_TURBOPACK if (experimentalTurbo) { - const { loadBindings, __isCustomTurbopackBinary, teardownHeapProfiler } = + const { loadBindings } = require('../build/swc') as typeof import('../build/swc') resetEnv() let bindings = await loadBindings() - // TODO(alexkirsz) Do we still need the `rawConfig` above? const config = await loadConfig( PHASE_DEVELOPMENT_SERVER, dir, @@ -266,6 +265,9 @@ const nextDev: CliCommand = async (argv) => { console.log(written) break } + default: + console.log(`skipping ${pathname} (${route.type})`) + break } } } From f31cefc5417eb843252a18474b333eec2418d18a Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 13 Jul 2023 16:56:06 +0200 Subject: [PATCH 8/9] Fix issue with output asset --- packages/next-swc/crates/napi/src/next_api/endpoint.rs | 6 ++++-- packages/next-swc/crates/napi/src/next_api/project.rs | 9 ++++++--- packages/next-swc/crates/next-core/src/emit.rs | 8 ++++++-- packages/next/src/cli/next-dev.ts | 6 +++--- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/packages/next-swc/crates/napi/src/next_api/endpoint.rs b/packages/next-swc/crates/napi/src/next_api/endpoint.rs index da10ebf0121dd..c966f3ae76280 100644 --- a/packages/next-swc/crates/napi/src/next_api/endpoint.rs +++ b/packages/next-swc/crates/napi/src/next_api/endpoint.rs @@ -1,5 +1,6 @@ use napi::{bindgen_prelude::External, JsFunction}; use next_api::route::{Endpoint, EndpointVc, WrittenEndpoint}; +use turbopack_binding::turbopack::core::error::PrettyPrintError; use super::utils::{subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc}; @@ -29,8 +30,9 @@ pub async fn endpoint_write_to_disk( let turbo_tasks = endpoint.turbo_tasks().clone(); let endpoint = **endpoint; let written = turbo_tasks - .run_once(endpoint.write_to_disk().strongly_consistent()) - .await?; + .run_once(async move { endpoint.write_to_disk().strongly_consistent().await }) + .await + .map_err(|e| napi::Error::from_reason(PrettyPrintError(&e).to_string()))?; // TODO peek_issues and diagnostics Ok((&*written).into()) } diff --git a/packages/next-swc/crates/napi/src/next_api/project.rs b/packages/next-swc/crates/napi/src/next_api/project.rs index 8a4a91d07f689..2c063e1f927ed 100644 --- a/packages/next-swc/crates/napi/src/next_api/project.rs +++ b/packages/next-swc/crates/napi/src/next_api/project.rs @@ -7,7 +7,9 @@ use next_api::{ route::{EndpointVc, Route}, }; use turbo_tasks::TurboTasks; -use turbopack_binding::turbo::tasks_memory::MemoryBackend; +use turbopack_binding::{ + turbo::tasks_memory::MemoryBackend, turbopack::core::error::PrettyPrintError, +}; use super::utils::{serde_enum_to_string, subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc}; use crate::register; @@ -54,8 +56,9 @@ pub async fn project_new(options: NapiProjectOptions) -> napi::Result { for (const [pathname, route] of entrypoints.routes) { switch (route.type) { case 'page': { - console.log(`writing ${pathname} to disk`) + Log.info(`writing ${pathname} to disk`) const written = await route.htmlEndpoint.writeToDisk() - console.log(written) + Log.info(written) break } default: - console.log(`skipping ${pathname} (${route.type})`) + Log.info(`skipping ${pathname} (${route.type})`) break } } From a38a1ce5cee3ee9b9ce124b07ae32abf21d4542d Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 13 Jul 2023 16:56:14 +0200 Subject: [PATCH 9/9] Link --- Cargo.lock | 70 +++++++++---------- Cargo.toml | 6 +- .../next-swc/crates/next-core/js/package.json | 4 +- pnpm-lock.yaml | 18 ++--- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68359ef994d9d..4aa8c24b5c0d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -412,7 +412,7 @@ dependencies = [ [[package]] name = "auto-hash-map" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "serde", ] @@ -3599,7 +3599,7 @@ dependencies = [ [[package]] name = "node-file-trace" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "serde", @@ -7259,7 +7259,7 @@ dependencies = [ [[package]] name = "turbo-tasks" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "auto-hash-map", @@ -7290,7 +7290,7 @@ dependencies = [ [[package]] name = "turbo-tasks-build" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "cargo-lock", @@ -7302,7 +7302,7 @@ dependencies = [ [[package]] name = "turbo-tasks-bytes" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "bytes", @@ -7317,7 +7317,7 @@ dependencies = [ [[package]] name = "turbo-tasks-env" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "dotenvs", @@ -7331,7 +7331,7 @@ dependencies = [ [[package]] name = "turbo-tasks-fetch" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "indexmap", @@ -7348,7 +7348,7 @@ dependencies = [ [[package]] name = "turbo-tasks-fs" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "auto-hash-map", @@ -7378,7 +7378,7 @@ dependencies = [ [[package]] name = "turbo-tasks-hash" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "base16", "hex", @@ -7390,7 +7390,7 @@ dependencies = [ [[package]] name = "turbo-tasks-macros" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "convert_case 0.6.0", @@ -7404,7 +7404,7 @@ dependencies = [ [[package]] name = "turbo-tasks-macros-shared" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "proc-macro2", "quote", @@ -7414,7 +7414,7 @@ dependencies = [ [[package]] name = "turbo-tasks-malloc" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "mimalloc", ] @@ -7422,7 +7422,7 @@ dependencies = [ [[package]] name = "turbo-tasks-memory" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "auto-hash-map", @@ -7445,7 +7445,7 @@ dependencies = [ [[package]] name = "turbo-tasks-testing" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "auto-hash-map", @@ -7458,7 +7458,7 @@ dependencies = [ [[package]] name = "turbopack" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "async-recursion", @@ -7488,7 +7488,7 @@ dependencies = [ [[package]] name = "turbopack-bench" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "chromiumoxide", @@ -7518,7 +7518,7 @@ dependencies = [ [[package]] name = "turbopack-binding" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "auto-hash-map", "mdxjs", @@ -7560,7 +7560,7 @@ dependencies = [ [[package]] name = "turbopack-build" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "indexmap", @@ -7580,7 +7580,7 @@ dependencies = [ [[package]] name = "turbopack-cli-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "clap 4.1.11", @@ -7604,7 +7604,7 @@ dependencies = [ [[package]] name = "turbopack-core" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "async-trait", @@ -7632,7 +7632,7 @@ dependencies = [ [[package]] name = "turbopack-create-test-app" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "clap 4.1.11", @@ -7645,7 +7645,7 @@ dependencies = [ [[package]] name = "turbopack-css" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "async-trait", @@ -7667,7 +7667,7 @@ dependencies = [ [[package]] name = "turbopack-dev" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "indexmap", @@ -7691,7 +7691,7 @@ dependencies = [ [[package]] name = "turbopack-dev-server" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "async-compression", @@ -7727,7 +7727,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "async-trait", @@ -7760,7 +7760,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript-plugins" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "async-trait", @@ -7783,7 +7783,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript-runtime" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "indoc", @@ -7800,7 +7800,7 @@ dependencies = [ [[package]] name = "turbopack-env" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "indexmap", @@ -7816,7 +7816,7 @@ dependencies = [ [[package]] name = "turbopack-image" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "base64 0.21.0", @@ -7836,7 +7836,7 @@ dependencies = [ [[package]] name = "turbopack-json" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "serde", @@ -7851,7 +7851,7 @@ dependencies = [ [[package]] name = "turbopack-mdx" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "mdxjs", @@ -7866,7 +7866,7 @@ dependencies = [ [[package]] name = "turbopack-node" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "async-stream", @@ -7901,7 +7901,7 @@ dependencies = [ [[package]] name = "turbopack-static" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "serde", @@ -7917,7 +7917,7 @@ dependencies = [ [[package]] name = "turbopack-swc-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "swc_core", "turbo-tasks", @@ -7928,7 +7928,7 @@ dependencies = [ [[package]] name = "turbopack-test-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?branch=sokra-alex/next-api#bcd458ebc2f43a7ad24684619c8cb4016491c8b5" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230713.3#e3c68fac81352b24bfcfa1f14b56c0ef0a391917" dependencies = [ "anyhow", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 87403c24ef618..4b309f31e9647 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,11 +44,11 @@ swc_core = { version = "0.79.13" } testing = { version = "0.33.20" } # Turbo crates -turbopack-binding = { git = "https://github.com/vercel/turbo.git", branch = "sokra-alex/next-api" } # last tag: "turbopack-230713.2" +turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230713.3" } # [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", branch = "sokra-alex/next-api" } # last tag: "turbopack-230713.2" +turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230713.3" } # [TODO]: need to refactor embed_directory! macro usage in next-core -turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", branch = "sokra-alex/next-api" } # last tag: "turbopack-230713.2" +turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230713.3" } # General Deps diff --git a/packages/next-swc/crates/next-core/js/package.json b/packages/next-swc/crates/next-core/js/package.json index efb6441cb911e..4cf4e5ce73ed7 100644 --- a/packages/next-swc/crates/next-core/js/package.json +++ b/packages/next-swc/crates/next-core/js/package.json @@ -10,8 +10,8 @@ "check": "tsc --noEmit" }, "dependencies": { - "@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5", - "@vercel/turbopack-node": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5", + "@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.3", + "@vercel/turbopack-node": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230713.3", "anser": "^2.1.1", "css.escape": "^1.5.1", "next": "*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3ebceea7857b2..cdfe4c6f2d405 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -992,8 +992,8 @@ importers: '@types/react': 18.2.7 '@types/react-dom': 18.2.4 '@vercel/ncc': ^0.36.0 - '@vercel/turbopack-ecmascript-runtime': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5 - '@vercel/turbopack-node': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5 + '@vercel/turbopack-ecmascript-runtime': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.3 + '@vercel/turbopack-node': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230713.3 anser: ^2.1.1 css.escape: ^1.5.1 find-up: ^6.3.0 @@ -1005,8 +1005,8 @@ importers: stacktrace-parser: ^0.1.10 strip-ansi: ^7.0.1 dependencies: - '@vercel/turbopack-ecmascript-runtime': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5_react-refresh@0.12.0' - '@vercel/turbopack-node': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5' + '@vercel/turbopack-ecmascript-runtime': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.3_react-refresh@0.12.0' + '@vercel/turbopack-node': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230713.3' anser: 2.1.1 css.escape: 1.5.1 next: link:../../../../next @@ -25498,9 +25498,9 @@ packages: /zwitch/2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5_react-refresh@0.12.0': - resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5} - id: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5' + '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.3_react-refresh@0.12.0': + resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.3} + id: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230713.3' name: '@vercel/turbopack-ecmascript-runtime' version: 0.0.0 dependencies: @@ -25511,8 +25511,8 @@ packages: - webpack dev: false - '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5': - resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?bcd458ebc2f43a7ad24684619c8cb4016491c8b5} + '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230713.3': + resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230713.3} name: '@vercel/turbopack-node' version: 0.0.0 dependencies: