From 9ed41664fad10c01626ebc2e9a4a65c791e4a036 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Thu, 2 Mar 2023 08:23:41 +0100 Subject: [PATCH] refactor internal modules (vercel/turbo#4018) ### Description * get rid of attached filesystem for our embedded modules * get rid of import "." in favor of inner assets depends on vercel/turbo#3999 ### Testing Instructions existing tests [X] Auto label --- .../js/src/entry/app/layout-entry.tsx | 3 +- .../js/src/entry/app/server-to-client-ssr.tsx | 9 +- .../js/src/entry/app/server-to-client.tsx | 4 +- crates/next-core/js/src/entry/config/next.js | 2 +- .../next-core/js/src/entry/next-hydrate.tsx | 3 +- crates/next-core/js/src/entry/page-loader.ts | 2 +- crates/next-core/js/src/entry/server-api.tsx | 4 +- crates/next-core/js/src/entry/server-data.tsx | 3 +- .../js/src/entry/server-edge-api.tsx | 4 +- .../js/src/entry/server-renderer.tsx | 7 +- .../next_layout_entry_transition.rs | 60 ++--- crates/next-core/src/app_source.rs | 15 +- crates/next-core/src/app_structure.rs | 3 - crates/next-core/src/babel.rs | 8 +- crates/next-core/src/embed_js.rs | 28 +-- crates/next-core/src/next_client/context.rs | 8 +- .../next-core/src/next_client/transition.rs | 60 +++-- .../src/next_client_chunks/with_chunks.rs | 2 + .../server_to_client_transition.rs | 67 ++++-- .../with_client_chunks.rs | 11 +- crates/next-core/src/next_config.rs | 17 +- crates/next-core/src/next_edge/context.rs | 2 +- crates/next-core/src/next_edge/transition.rs | 6 +- crates/next-core/src/next_font_google/mod.rs | 12 +- crates/next-core/src/next_import_map.rs | 97 ++++---- crates/next-core/src/next_server/context.rs | 30 +-- crates/next-core/src/page_loader.rs | 29 +-- crates/next-core/src/page_source.rs | 85 ++++--- crates/next-core/src/pages_structure.rs | 4 +- crates/next-core/src/router.rs | 34 ++- crates/next-core/src/router_source.rs | 2 +- crates/next-core/src/web_entry_source.rs | 13 +- .../at-next-font/input/pages/index.js | 2 +- .../font-google/basic/input/pages/index.js | 6 +- ...ar__0__star__) is very dynamic-5efef4.txt} | 6 +- ..._utf-8__quo__) is very dynamic-f84517.txt} | 6 +- ...ar__0__star__) is very dynamic-dd45bc.txt} | 6 +- ... Error evaluating Node.js code-bf8568.txt} | 2 +- ...ror resolving commonjs request-e56948.txt} | 4 +- ...ing EcmaScript Modules request-6adb45.txt} | 4 +- ...ing EcmaScript Modules request-d56c20.txt} | 4 +- ...ing EcmaScript Modules request-eb66f2.txt} | 4 +- ...ror resolving commonjs request-d35c6e.txt} | 4 +- ...rror resolving commonjs request-354825.txt | 11 - ...ror resolving commonjs request-d795f8.txt} | 4 +- ..._.__b__quo__]) is very dynamic-1b7b2d.txt} | 6 +- ...rror resolving commonjs request-0baf48.txt | 11 + ..._.__c__quo__]) is very dynamic-c9f4f1.txt} | 6 +- crates/turbopack-core/src/reference_type.rs | 3 + crates/turbopack-core/src/resolve/mod.rs | 58 +++-- crates/turbopack-core/src/resolve/options.rs | 20 ++ .../src/chunk_group_files_asset.rs | 11 +- crates/turbopack-node/src/evaluate.rs | 12 +- .../turbopack-node/src/execution_context.rs | 13 +- crates/turbopack-node/src/pool.rs | 3 + .../turbopack-node/src/transforms/postcss.rs | 12 +- .../turbopack-node/src/transforms/webpack.rs | 12 +- crates/turbopack-tests/tests/snapshot.rs | 4 +- crates/turbopack/examples/turbopack.rs | 2 +- crates/turbopack/src/evaluate_context.rs | 13 +- crates/turbopack/src/lib.rs | 211 ++++++++---------- crates/turbopack/src/module_options/mod.rs | 12 +- crates/turbopack/src/resolve.rs | 4 +- .../turbopack/src/resolve_options_context.rs | 5 +- crates/turbopack/src/transition/mod.rs | 37 ++- crates/turbopack/tests/node-file-trace.rs | 2 +- 66 files changed, 609 insertions(+), 545 deletions(-) rename crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/{lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-c19e79.txt => lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-5efef4.txt} (77%) rename crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/{lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-58d7af.txt => lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-f84517.txt} (77%) rename crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/{lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-667243.txt => lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-dd45bc.txt} (78%) rename crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/{Error evaluating Node.js code-28e1f2.txt => Error evaluating Node.js code-bf8568.txt} (77%) rename crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/{Error resolving commonjs request-6b96ad.txt => Error resolving commonjs request-e56948.txt} (52%) rename crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/{Error resolving EcmaScript Modules request-431056.txt => Error resolving EcmaScript Modules request-6adb45.txt} (50%) rename crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/{Error resolving EcmaScript Modules request-1a1150.txt => Error resolving EcmaScript Modules request-d56c20.txt} (50%) rename crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/{Error resolving EcmaScript Modules request-a3050d.txt => Error resolving EcmaScript Modules request-eb66f2.txt} (50%) rename crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/issues/{Error resolving commonjs request-92a826.txt => Error resolving commonjs request-d35c6e.txt} (51%) delete mode 100644 crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/Error resolving commonjs request-354825.txt rename crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/{weak-dependencies/issues/Error resolving commonjs request-86b73f.txt => weak-dependencies-context/issues/Error resolving commonjs request-d795f8.txt} (50%) rename crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/{lint TP1002 require([__quo__.__b__quo__]) is very dynamic-8bc115.txt => lint TP1002 require([__quo__.__b__quo__]) is very dynamic-1b7b2d.txt} (72%) create mode 100644 crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/Error resolving commonjs request-0baf48.txt rename crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/{lint TP1002 require([__quo__.__c__quo__]) is very dynamic-80ea5a.txt => lint TP1002 require([__quo__.__c__quo__]) is very dynamic-c9f4f1.txt} (73%) diff --git a/crates/next-core/js/src/entry/app/layout-entry.tsx b/crates/next-core/js/src/entry/app/layout-entry.tsx index 2c176193238e6..7ceb7ce7fae56 100644 --- a/crates/next-core/js/src/entry/app/layout-entry.tsx +++ b/crates/next-core/js/src/entry/app/layout-entry.tsx @@ -8,5 +8,6 @@ import * as serverHooks from "next/dist/client/components/hooks-server-context.j export { serverHooks }; export { renderToReadableStream } from "next/dist/compiled/react-server-dom-webpack/server.edge"; -import * as module from "."; +// @ts-expect-error PAGE is provided by rust +import * as module from "PAGE"; export { module }; diff --git a/crates/next-core/js/src/entry/app/server-to-client-ssr.tsx b/crates/next-core/js/src/entry/app/server-to-client-ssr.tsx index 6497c6f59a8e8..8b7dfa3a36c2d 100644 --- a/crates/next-core/js/src/entry/app/server-to-client-ssr.tsx +++ b/crates/next-core/js/src/entry/app/server-to-client-ssr.tsx @@ -1,9 +1,10 @@ import { createProxy } from "next/dist/build/webpack/loaders/next-flight-loader/module-proxy"; -("TURBOPACK { transition: next-ssr-client-module; chunking-type: parallel }"); -import { __turbopack_module_id__ as id } from "."; +("TURBOPACK { chunking-type: parallel }"); +// @ts-expect-error CLIENT_MODULE is provided by rust +import { __turbopack_module_id__ as id } from "CLIENT_MODULE"; -("TURBOPACK { transition: next-client-chunks }"); -import client_id, { chunks } from "."; +// @ts-expect-error CLIENT_CHUNKS is provided by rust +import client_id, { chunks } from "CLIENT_CHUNKS"; export default createProxy(JSON.stringify([client_id, chunks, id])); diff --git a/crates/next-core/js/src/entry/app/server-to-client.tsx b/crates/next-core/js/src/entry/app/server-to-client.tsx index 02d1539486c47..30c569c4df514 100644 --- a/crates/next-core/js/src/entry/app/server-to-client.tsx +++ b/crates/next-core/js/src/entry/app/server-to-client.tsx @@ -1,6 +1,6 @@ import { createProxy } from "next/dist/build/webpack/loaders/next-flight-loader/module-proxy"; -("TURBOPACK { transition: next-client-chunks }"); -import client_id, { chunks } from "."; +// @ts-expect-error CLIENT_CHUNKS is provided by rust +import client_id, { chunks } from "CLIENT_CHUNKS"; export default createProxy(JSON.stringify([client_id, chunks])); diff --git a/crates/next-core/js/src/entry/config/next.js b/crates/next-core/js/src/entry/config/next.js index 487dfc0529ec6..fd5d53bfd28b0 100644 --- a/crates/next-core/js/src/entry/config/next.js +++ b/crates/next-core/js/src/entry/config/next.js @@ -1,7 +1,7 @@ import loadConfig from "next/dist/server/config"; import loadCustomRoutes from "next/dist/lib/load-custom-routes"; import { PHASE_DEVELOPMENT_SERVER } from "next/dist/shared/lib/constants"; -import assert from "assert"; +import assert from "node:assert"; const loadNextConfig = async (silent) => { const nextConfig = await loadConfig( diff --git a/crates/next-core/js/src/entry/next-hydrate.tsx b/crates/next-core/js/src/entry/next-hydrate.tsx index e4c6fa3dbbb50..b7fa676454533 100644 --- a/crates/next-core/js/src/entry/next-hydrate.tsx +++ b/crates/next-core/js/src/entry/next-hydrate.tsx @@ -20,7 +20,8 @@ import { } from "@vercel/turbopack-next/dev/hmr-client"; import * as _app from "@vercel/turbopack-next/pages/_app"; -import * as page from "."; +// @ts-expect-error PAGE is provided by rust +import * as page from "PAGE"; async function loadPageChunk(assetPrefix: string, chunkPath: string) { const fullPath = assetPrefix + chunkPath; diff --git a/crates/next-core/js/src/entry/page-loader.ts b/crates/next-core/js/src/entry/page-loader.ts index 306f7cf82a28a..743c1935f0317 100644 --- a/crates/next-core/js/src/entry/page-loader.ts +++ b/crates/next-core/js/src/entry/page-loader.ts @@ -1,4 +1,4 @@ -import * as page from "."; +import * as page from "PAGE"; // inserted by rust code declare const PAGE_PATH: string; diff --git a/crates/next-core/js/src/entry/server-api.tsx b/crates/next-core/js/src/entry/server-api.tsx index 429bd16517d73..12f0e79576a65 100644 --- a/crates/next-core/js/src/entry/server-api.tsx +++ b/crates/next-core/js/src/entry/server-api.tsx @@ -4,9 +4,9 @@ import startHandler from "@vercel/turbopack-next/internal/api-server-handler"; import "next/dist/server/node-polyfill-fetch.js"; -import * as allExports from "."; +// @ts-expect-error INNER is provided by rust +import * as allExports from "INNER"; import { apiResolver } from "next/dist/server/api-utils/node"; -import { IncomingMessage, ServerResponse } from "node:http"; import { NodeNextRequest, NodeNextResponse, diff --git a/crates/next-core/js/src/entry/server-data.tsx b/crates/next-core/js/src/entry/server-data.tsx index 4249bfb87e4ac..67ebcdeade10b 100644 --- a/crates/next-core/js/src/entry/server-data.tsx +++ b/crates/next-core/js/src/entry/server-data.tsx @@ -5,7 +5,8 @@ import startHandler from "@vercel/turbopack-next/internal/page-server-handler"; // eslint-disable-next-line import Document from "next/document"; import App from "next/app"; -import * as otherExports from "."; +// @ts-expect-error INNER is provided by rust +import * as otherExports from "INNER"; startHandler({ isDataReq: true, diff --git a/crates/next-core/js/src/entry/server-edge-api.tsx b/crates/next-core/js/src/entry/server-edge-api.tsx index 1903c8b911d7b..fba2d3f536776 100644 --- a/crates/next-core/js/src/entry/server-edge-api.tsx +++ b/crates/next-core/js/src/entry/server-edge-api.tsx @@ -7,8 +7,8 @@ import { join } from "path"; import "next/dist/server/node-polyfill-fetch.js"; -("TURBOPACK { transition: next-edge }"); -import chunkGroup from "."; +// @ts-expect-error INNER_EDGE_CHUNK_GROUP is provided by rust +import chunkGroup from "INNER_EDGE_CHUNK_GROUP"; import { NodeNextRequest, diff --git a/crates/next-core/js/src/entry/server-renderer.tsx b/crates/next-core/js/src/entry/server-renderer.tsx index 35d141db42a36..6280bc6cc0989 100644 --- a/crates/next-core/js/src/entry/server-renderer.tsx +++ b/crates/next-core/js/src/entry/server-renderer.tsx @@ -5,10 +5,11 @@ import startHandler from "@vercel/turbopack-next/internal/page-server-handler"; import App from "@vercel/turbopack-next/pages/_app"; import Document from "@vercel/turbopack-next/pages/_document"; -import Component, * as otherExports from "."; +// @ts-expect-error INNER is provided by rust +import Component, * as otherExports from "INNER"; -("TURBOPACK { transition: next-client }"); -import chunkGroup from "."; +// @ts-expect-error INNER_CLIENT_CHUNK_GROUP is provided by rust +import chunkGroup from "INNER_CLIENT_CHUNK_GROUP"; startHandler({ isDataReq: false, diff --git a/crates/next-core/src/app_render/next_layout_entry_transition.rs b/crates/next-core/src/app_render/next_layout_entry_transition.rs index cb6cb306a716f..f372c7682da2f 100644 --- a/crates/next-core/src/app_render/next_layout_entry_transition.rs +++ b/crates/next-core/src/app_render/next_layout_entry_transition.rs @@ -1,4 +1,6 @@ use anyhow::Result; +use indexmap::indexmap; +use turbo_tasks::Value; use turbo_tasks_fs::FileSystemPathVc; use turbopack::{ self, @@ -7,15 +9,14 @@ use turbopack::{ transition::{Transition, TransitionVc}, ModuleAssetContextVc, }; -use turbopack_core::{ - asset::{Asset, AssetVc}, - compile_time_info::CompileTimeInfoVc, - virtual_asset::VirtualAssetVc, +use turbopack_core::{asset::AssetVc, compile_time_info::CompileTimeInfoVc, context::AssetContext}; +use turbopack_ecmascript::{ + EcmascriptInputTransform, EcmascriptInputTransformsVc, EcmascriptModuleAssetType, + EcmascriptModuleAssetVc, InnerAssetsVc, }; -use turbopack_ecmascript::chunk::EcmascriptChunkPlaceableVc; use crate::{ - embed_js::next_js_file, next_client_component::with_client_chunks::WithClientChunksAsset, + embed_js::next_asset, next_client_component::with_client_chunks::WithClientChunksAsset, }; #[turbo_tasks::value(shared)] @@ -28,15 +29,6 @@ pub struct NextLayoutEntryTransition { #[turbo_tasks::value_impl] impl Transition for NextLayoutEntryTransition { - #[turbo_tasks::function] - fn process_source(&self, asset: AssetVc) -> AssetVc { - VirtualAssetVc::new( - asset.ident().path().join("layout-entry.tsx"), - next_js_file("entry/app/layout-entry.tsx").into(), - ) - .into() - } - #[turbo_tasks::function] fn process_compile_time_info( &self, @@ -65,20 +57,30 @@ impl Transition for NextLayoutEntryTransition { async fn process_module( &self, asset: AssetVc, - _context: ModuleAssetContextVc, + context: ModuleAssetContextVc, ) -> Result { - Ok( - if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? { - WithClientChunksAsset { - asset: placeable, - // next.js code already adds _next prefix - server_root: self.server_root.join("_next"), - } - .cell() - .into() - } else { - asset - }, - ) + let internal_asset = next_asset("entry/app/layout-entry.tsx"); + + let asset = EcmascriptModuleAssetVc::new_with_inner_assets( + internal_asset, + context.into(), + Value::new(EcmascriptModuleAssetType::Typescript), + EcmascriptInputTransformsVc::cell(vec![ + EcmascriptInputTransform::TypeScript, + EcmascriptInputTransform::React { refresh: false }, + ]), + context.compile_time_info(), + InnerAssetsVc::cell(indexmap! { + "PAGE".to_string() => asset + }), + ); + + Ok(WithClientChunksAsset { + asset: asset.into(), + // next.js code already adds _next prefix + server_root: self.server_root.join("_next"), + } + .cell() + .into()) } } diff --git a/crates/next-core/src/app_source.rs b/crates/next-core/src/app_source.rs index 9db646a122343..14c75bcc9a895 100644 --- a/crates/next-core/src/app_source.rs +++ b/crates/next-core/src/app_source.rs @@ -4,7 +4,7 @@ use std::{ }; use anyhow::{anyhow, Result}; -use indexmap::IndexMap; +use indexmap::indexmap; use turbo_tasks::{TryJoinIterExt, Value, ValueToString}; use turbo_tasks_env::ProcessEnvVc; use turbo_tasks_fs::{rebase, rope::RopeBuilder, File, FileContent, FileSystemPathVc}; @@ -46,7 +46,7 @@ use crate::{ next_layout_entry_transition::NextLayoutEntryTransition, LayoutSegment, LayoutSegmentsVc, }, app_structure::{AppStructure, AppStructureItem, AppStructureVc, OptionAppStructureVc}, - embed_js::{next_js_file, wrap_with_next_js_fs}, + embed_js::next_js_file, env::env_for_js, fallback::get_fallback_page, next_client::{ @@ -314,8 +314,6 @@ pub async fn create_app_source( next_config: NextConfigVc, server_addr: ServerAddrVc, ) -> Result { - let project_path = wrap_with_next_js_fs(project_path); - let Some(app_structure) = *app_structure.await? else { return Ok(NoContentSourceVc::new().into()); }; @@ -363,7 +361,7 @@ pub async fn create_app_source( next_config, ); - Ok(create_app_source_for_directory( + let source = create_app_source_for_directory( app_structure, context_ssr, context, @@ -372,7 +370,8 @@ pub async fn create_app_source( EcmascriptChunkPlaceablesVc::cell(server_runtime_entries), fallback_page, output_path, - )) + ); + Ok(source) } #[allow(clippy::too_many_arguments)] @@ -717,7 +716,9 @@ impl AppRouteVc { Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), this.context.compile_time_info(), - InnerAssetsVc::cell(IndexMap::from([("ROUTE_CHUNK_GROUP".to_string(), entry)])), + InnerAssetsVc::cell(indexmap! { + "ROUTE_CHUNK_GROUP".to_string() => entry + }), ), chunking_context, intermediate_output_path: this.intermediate_output_path, diff --git a/crates/next-core/src/app_structure.rs b/crates/next-core/src/app_structure.rs index 83b819bfd6a4e..4bae35699df9a 100644 --- a/crates/next-core/src/app_structure.rs +++ b/crates/next-core/src/app_structure.rs @@ -13,7 +13,6 @@ use turbopack_dev_server::source::specificity::SpecificityVc; use crate::{ app_render::{LayoutSegment, LayoutSegmentVc, LayoutSegmentsVc}, - embed_js::wrap_with_next_js_fs, next_config::NextConfigVc, }; @@ -101,8 +100,6 @@ pub async fn find_app_structure( server_root: FileSystemPathVc, next_config: NextConfigVc, ) -> Result { - let project_path = wrap_with_next_js_fs(project_path); - if !*next_config.app_dir().await? { return Ok(OptionAppStructureVc::cell(None)); } diff --git a/crates/next-core/src/babel.rs b/crates/next-core/src/babel.rs index 95c36bdf935d2..15bcfe7778fee 100644 --- a/crates/next-core/src/babel.rs +++ b/crates/next-core/src/babel.rs @@ -117,16 +117,16 @@ pub async fn maybe_add_babel_loader( } #[turbo_tasks::function] -pub async fn is_babel_loader_available(project_root: FileSystemPathVc) -> Result { +pub async fn is_babel_loader_available(project_path: FileSystemPathVc) -> Result { let result = resolve( - project_root, + project_path, RequestVc::parse(Value::new(Pattern::Constant( "babel-loader/package.json".to_string(), ))), resolve_options( - project_root, + project_path, ResolveOptionsContext { - enable_node_modules: true, + enable_node_modules: Some(project_path.root().resolve().await?), enable_node_native_modules: true, custom_conditions: vec!["development".to_string()], ..Default::default() diff --git a/crates/next-core/src/embed_js.rs b/crates/next-core/src/embed_js.rs index eac3971c5a25b..c5dfee8fc7949 100644 --- a/crates/next-core/src/embed_js.rs +++ b/crates/next-core/src/embed_js.rs @@ -1,9 +1,5 @@ -use anyhow::Result; -use turbo_tasks_fs::{ - attach::AttachedFileSystemVc, embed_directory, FileContentVc, FileSystem, FileSystemPathVc, - FileSystemVc, -}; -use turbopack_core::{asset::AssetVc, virtual_asset::VirtualAssetVc}; +use turbo_tasks_fs::{embed_directory, FileContentVc, FileSystem, FileSystemPathVc, FileSystemVc}; +use turbopack_core::{asset::AssetVc, source_asset::SourceAssetVc}; pub const VIRTUAL_PACKAGE_NAME: &str = "@vercel/turbopack-next"; @@ -23,22 +19,6 @@ pub(crate) fn next_js_file_path(path: &str) -> FileSystemPathVc { } #[turbo_tasks::function] -pub(crate) async fn attached_next_js_package_path( - project_path: FileSystemPathVc, -) -> FileSystemPathVc { - project_path.join(&format!("[embedded_modules]/{}", VIRTUAL_PACKAGE_NAME)) -} - -#[turbo_tasks::function] -pub(crate) async fn wrap_with_next_js_fs( - project_path: FileSystemPathVc, -) -> Result { - let attached_path = attached_next_js_package_path(project_path); - let fs = AttachedFileSystemVc::new(attached_path, next_js_fs()); - Ok(fs.convert_path(project_path)) -} - -#[turbo_tasks::function] -pub(crate) fn next_asset(asset_path: FileSystemPathVc, path: &str) -> AssetVc { - VirtualAssetVc::new(asset_path, next_js_file(path).into()).into() +pub(crate) fn next_asset(path: &str) -> AssetVc { + SourceAssetVc::new(next_js_file_path(path)).into() } diff --git a/crates/next-core/src/next_client/context.rs b/crates/next-core/src/next_client/context.rs index 09ff7771e4bb3..f2925eec33ce1 100644 --- a/crates/next-core/src/next_client/context.rs +++ b/crates/next-core/src/next_client/context.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use anyhow::Result; use turbo_tasks::{primitives::StringVc, Value}; use turbo_tasks_env::ProcessEnvVc; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks_fs::{FileSystem, FileSystemPathVc}; use turbopack::{ module_options::{ module_options_context::{ModuleOptionsContext, ModuleOptionsContextVc}, @@ -28,7 +28,7 @@ use turbopack_node::execution_context::ExecutionContextVc; use super::transforms::get_next_client_transforms_rules; use crate::{ babel::maybe_add_babel_loader, - embed_js::attached_next_js_package_path, + embed_js::next_js_fs, env::env_for_js, next_build::{get_external_next_compiled_package_mapping, get_postcss_package_mapping}, next_client::runtime_entry::{RuntimeEntriesVc, RuntimeEntry}, @@ -89,7 +89,7 @@ pub async fn get_client_resolve_options_context( let next_client_fallback_import_map = get_next_client_fallback_import_map(ty); let next_client_resolved_map = get_next_client_resolved_map(project_path, project_path); let module_options_context = ResolveOptionsContext { - enable_node_modules: true, + enable_node_modules: Some(project_path.root().resolve().await?), custom_conditions: vec!["development".to_string()], import_map: Some(next_client_import_map), fallback_import_map: Some(next_client_fallback_import_map), @@ -268,7 +268,7 @@ pub async fn get_client_runtime_entries( RequestVc::parse(Value::new(Pattern::Constant( "./dev/bootstrap.ts".to_string(), ))), - attached_next_js_package_path(project_root).join("_"), + next_js_fs().root().join("_"), ) .cell(), ); diff --git a/crates/next-core/src/next_client/transition.rs b/crates/next-core/src/next_client/transition.rs index 18993dbcf970b..6d8d8441a1f7b 100644 --- a/crates/next-core/src/next_client/transition.rs +++ b/crates/next-core/src/next_client/transition.rs @@ -1,5 +1,6 @@ -use anyhow::{bail, Result}; -use turbo_tasks::ValueToString; +use anyhow::Result; +use indexmap::indexmap; +use turbo_tasks::Value; use turbo_tasks_fs::FileSystemPathVc; use turbopack::{ ecmascript::chunk_group_files_asset::ChunkGroupFilesAsset, @@ -9,14 +10,16 @@ use turbopack::{ ModuleAssetContextVc, }; use turbopack_core::{ - asset::{Asset, AssetVc}, - chunk::{ChunkableAssetVc, ChunkingContextVc}, - compile_time_info::CompileTimeInfoVc, - virtual_asset::VirtualAssetVc, + asset::AssetVc, chunk::ChunkingContextVc, compile_time_info::CompileTimeInfoVc, + context::AssetContext, +}; +use turbopack_ecmascript::{ + EcmascriptInputTransform, EcmascriptInputTransformsVc, EcmascriptModuleAssetType, + EcmascriptModuleAssetVc, InnerAssetsVc, }; use super::runtime_entry::RuntimeEntriesVc; -use crate::embed_js::next_js_file; +use crate::embed_js::next_asset; /// Makes a transition into a next.js client context. /// @@ -36,23 +39,6 @@ pub struct NextClientTransition { #[turbo_tasks::value_impl] impl Transition for NextClientTransition { - #[turbo_tasks::function] - fn process_source(&self, asset: AssetVc) -> AssetVc { - if self.is_app { - VirtualAssetVc::new( - asset.ident().path().join("next-app-hydrate.tsx"), - next_js_file("entry/app/hydrate.tsx").into(), - ) - .into() - } else { - VirtualAssetVc::new( - asset.ident().path().join("next-hydrate.tsx"), - next_js_file("entry/next-hydrate.tsx").into(), - ) - .into() - } - } - #[turbo_tasks::function] fn process_compile_time_info( &self, @@ -83,18 +69,30 @@ impl Transition for NextClientTransition { asset: AssetVc, context: ModuleAssetContextVc, ) -> Result { - let chunkable_asset = match ChunkableAssetVc::resolve_from(asset).await? { - Some(chunkable_asset) => chunkable_asset, - None => bail!( - "asset {} is not chunkable", - asset.ident().to_string().await? - ), + let internal_asset = if self.is_app { + next_asset("entry/app/hydrate.tsx") + } else { + next_asset("entry/next-hydrate.tsx") }; + let asset = EcmascriptModuleAssetVc::new_with_inner_assets( + internal_asset, + context.into(), + Value::new(EcmascriptModuleAssetType::Typescript), + EcmascriptInputTransformsVc::cell(vec![ + EcmascriptInputTransform::TypeScript, + EcmascriptInputTransform::React { refresh: false }, + ]), + context.compile_time_info(), + InnerAssetsVc::cell(indexmap! { + "PAGE".to_string() => asset + }), + ); + let runtime_entries = self.runtime_entries.resolve_entries(context.into()); let asset = ChunkGroupFilesAsset { - asset: chunkable_asset, + asset: asset.into(), chunking_context: self.client_chunking_context, base_path: self.server_root.join("_next"), runtime_entries: Some(runtime_entries), diff --git a/crates/next-core/src/next_client_chunks/with_chunks.rs b/crates/next-core/src/next_client_chunks/with_chunks.rs index 3f2d26b2a8f00..419fc64778eee 100644 --- a/crates/next-core/src/next_client_chunks/with_chunks.rs +++ b/crates/next-core/src/next_client_chunks/with_chunks.rs @@ -74,6 +74,7 @@ impl EcmascriptChunkPlaceable for WithChunksAsset { context, inner_context: this.chunking_context, inner: self_vc, + chunk_item: this.asset.as_chunk_item(context), } .cell() .into()) @@ -91,6 +92,7 @@ struct WithChunksChunkItem { context: ChunkingContextVc, inner_context: ChunkingContextVc, inner: WithChunksAssetVc, + chunk_item: EcmascriptChunkItemVc, } #[turbo_tasks::value_impl] diff --git a/crates/next-core/src/next_client_component/server_to_client_transition.rs b/crates/next-core/src/next_client_component/server_to_client_transition.rs index 558fefcb504ca..934818ab0af23 100644 --- a/crates/next-core/src/next_client_component/server_to_client_transition.rs +++ b/crates/next-core/src/next_client_component/server_to_client_transition.rs @@ -1,10 +1,21 @@ -use turbopack::transition::{Transition, TransitionVc}; +use anyhow::Result; +use indexmap::indexmap; +use turbo_tasks::Value; +use turbopack::{ + transition::{Transition, TransitionVc}, + ModuleAssetContextVc, +}; use turbopack_core::{ - asset::{Asset, AssetVc}, - virtual_asset::VirtualAssetVc, + asset::AssetVc, + context::AssetContext, + reference_type::{EntryReferenceSubType, ReferenceType}, +}; +use turbopack_ecmascript::{ + EcmascriptInputTransform, EcmascriptInputTransformsVc, EcmascriptModuleAssetType, + EcmascriptModuleAssetVc, InnerAssetsVc, }; -use crate::embed_js::next_js_file; +use crate::embed_js::next_asset; #[turbo_tasks::value(shared)] pub struct NextServerToClientTransition { @@ -14,16 +25,44 @@ pub struct NextServerToClientTransition { #[turbo_tasks::value_impl] impl Transition for NextServerToClientTransition { #[turbo_tasks::function] - fn process_source(&self, asset: AssetVc) -> AssetVc { - VirtualAssetVc::new( - asset.ident().path().join("client-proxy.tsx"), - next_js_file(if self.ssr { - "entry/app/server-to-client-ssr.tsx" - } else { - "entry/app/server-to-client.tsx" - }) - .into(), + async fn process( + self_vc: NextServerToClientTransitionVc, + asset: AssetVc, + context: ModuleAssetContextVc, + _reference_type: Value, + ) -> Result { + let internal_asset = next_asset(if self_vc.await?.ssr { + "entry/app/server-to-client-ssr.tsx" + } else { + "entry/app/server-to-client.tsx" + }); + let context = self_vc.process_context(context); + let client_chunks = context.with_transition("next-client-chunks").process( + asset, + Value::new(ReferenceType::Entry( + EntryReferenceSubType::AppClientComponent, + )), + ); + let client_module = context.with_transition("next-ssr-client-module").process( + asset, + Value::new(ReferenceType::Entry( + EntryReferenceSubType::AppClientComponent, + )), + ); + Ok(EcmascriptModuleAssetVc::new_with_inner_assets( + internal_asset, + context.into(), + Value::new(EcmascriptModuleAssetType::Typescript), + EcmascriptInputTransformsVc::cell(vec![ + EcmascriptInputTransform::TypeScript, + EcmascriptInputTransform::React { refresh: false }, + ]), + context.compile_time_info(), + InnerAssetsVc::cell(indexmap! { + "CLIENT_MODULE".to_string() => client_module, + "CLIENT_CHUNKS".to_string() => client_chunks, + }), ) - .into() + .into()) } } diff --git a/crates/next-core/src/next_client_component/with_client_chunks.rs b/crates/next-core/src/next_client_component/with_client_chunks.rs index 82f90787d544b..b39f5317ed8f4 100644 --- a/crates/next-core/src/next_client_component/with_client_chunks.rs +++ b/crates/next-core/src/next_client_component/with_client_chunks.rs @@ -68,16 +68,18 @@ impl ChunkableAsset for WithClientChunksAsset { #[turbo_tasks::value_impl] impl EcmascriptChunkPlaceable for WithClientChunksAsset { #[turbo_tasks::function] - fn as_chunk_item( + async fn as_chunk_item( self_vc: WithClientChunksAssetVc, context: ChunkingContextVc, - ) -> EcmascriptChunkItemVc { - WithClientChunksChunkItem { + ) -> Result { + let this = self_vc.await?; + Ok(WithClientChunksChunkItem { context: context.with_layer("rsc"), inner: self_vc, + chunk_item: this.asset.as_chunk_item(context), } .cell() - .into() + .into()) } #[turbo_tasks::function] @@ -91,6 +93,7 @@ impl EcmascriptChunkPlaceable for WithClientChunksAsset { struct WithClientChunksChunkItem { context: ChunkingContextVc, inner: WithClientChunksAssetVc, + chunk_item: EcmascriptChunkItemVc, } #[turbo_tasks::value_impl] diff --git a/crates/next-core/src/next_config.rs b/crates/next-core/src/next_config.rs index d8c3cfb06004f..c3dc4174c6ac6 100644 --- a/crates/next-core/src/next_config.rs +++ b/crates/next-core/src/next_config.rs @@ -540,7 +540,7 @@ fn next_configs() -> StringsVc { #[turbo_tasks::function] pub async fn load_next_config(execution_context: ExecutionContextVc) -> Result { let ExecutionContext { - project_root, + project_path, intermediate_output_path, env, } = *execution_context.await?; @@ -551,8 +551,8 @@ pub async fn load_next_config(execution_context: ExecutionContextVc) -> Result Some(SourceAssetVc::new(*config_path)), FindContextFileResult::NotFound(_) => None, @@ -570,19 +570,16 @@ pub async fn load_next_config(execution_context: ExecutionContextVc) -> Result asset + }), ); let asset = ChunkGroupFilesAsset { diff --git a/crates/next-core/src/next_font_google/mod.rs b/crates/next-core/src/next_font_google/mod.rs index c8370af56a6a6..442bba996905d 100644 --- a/crates/next-core/src/next_font_google/mod.rs +++ b/crates/next-core/src/next_font_google/mod.rs @@ -22,7 +22,7 @@ use turbopack_core::{ use self::options::FontWeights; use crate::{ - embed_js::attached_next_js_package_path, + embed_js::next_js_file_path, next_font_google::{ options::FontDataEntry, util::{get_font_axes, get_stylesheet_url}, @@ -76,8 +76,8 @@ impl ImportMappingReplacement for NextFontGoogleReplacer { let properties = get_font_css_properties(get_scoped_font_family(*query_vc), options).await?; let js_asset = VirtualAssetVc::new( - attached_next_js_package_path(self.project_path) - .join(&format!("internal/font/google/{}.js", get_request_id(*query_vc).await?)), + next_js_file_path("internal/font/google") + .join(&format!("{}.js", get_request_id(*query_vc).await?)), FileContent::Content( formatdoc!( r#" @@ -155,10 +155,8 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer { let options = font_options_from_query_map(*query_vc); let stylesheet_url = get_stylesheet_url_from_options(options); let scoped_font_family = get_scoped_font_family(*query_vc); - let css_virtual_path = attached_next_js_package_path(self.project_path).join(&format!( - "internal/font/google/{}.module.css", - get_request_id(*query_vc).await? - )); + let css_virtual_path = next_js_file_path("internal/font/google") + .join(&format!("/{}.module.css", get_request_id(*query_vc).await?)); let stylesheet_res = fetch( stylesheet_url, diff --git a/crates/next-core/src/next_import_map.rs b/crates/next-core/src/next_import_map.rs index cc81c4a9321a9..426f761c9fcb0 100644 --- a/crates/next-core/src/next_import_map.rs +++ b/crates/next-core/src/next_import_map.rs @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, HashMap}; use anyhow::{Context, Result}; use turbo_tasks::Value; -use turbo_tasks_fs::{glob::GlobVc, FileSystemPathVc}; +use turbo_tasks_fs::{glob::GlobVc, FileSystem, FileSystemPathVc}; use turbopack::{resolve_options, resolve_options_context::ResolveOptionsContext}; use turbopack_core::{ asset::Asset, @@ -18,7 +18,7 @@ use turbopack_core::{ }; use crate::{ - embed_js::{attached_next_js_package_path, VIRTUAL_PACKAGE_NAME}, + embed_js::{next_js_fs, VIRTUAL_PACKAGE_NAME}, next_client::context::ClientContextType, next_config::NextConfigVc, next_font_google::{NextFontGoogleCssModuleReplacerVc, NextFontGoogleReplacerVc}, @@ -116,21 +116,21 @@ pub async fn get_next_client_import_map( /// Computes the Next-specific client import map. #[turbo_tasks::function] -pub fn get_next_build_import_map(project_path: FileSystemPathVc) -> ImportMapVc { +pub fn get_next_build_import_map() -> ImportMapVc { let mut import_map = ImportMap::empty(); - let package_root = attached_next_js_package_path(project_path); - insert_package_alias( &mut import_map, &format!("{VIRTUAL_PACKAGE_NAME}/"), - package_root, + next_js_fs().root(), ); - import_map.insert_exact_alias("next", ImportMapping::External(None).into()); - import_map.insert_wildcard_alias("next/", ImportMapping::External(None).into()); - import_map.insert_exact_alias("styled-jsx", ImportMapping::External(None).into()); - import_map.insert_wildcard_alias("styled-jsx/", ImportMapping::External(None).into()); + let external = ImportMapping::External(None).cell(); + + import_map.insert_exact_alias("next", external); + import_map.insert_wildcard_alias("next/", external); + import_map.insert_exact_alias("styled-jsx", external); + import_map.insert_wildcard_alias("styled-jsx/", external); import_map.cell() } @@ -188,33 +188,28 @@ pub async fn get_next_server_import_map( let ty = ty.into_value(); insert_next_server_special_aliases(&mut import_map, ty).await?; + let external = ImportMapping::External(None).cell(); match ty { ServerContextType::Pages { .. } | ServerContextType::PagesData { .. } => { - import_map.insert_exact_alias("next", ImportMapping::External(None).into()); - import_map.insert_wildcard_alias("next/", ImportMapping::External(None).into()); - import_map.insert_exact_alias("react", ImportMapping::External(None).into()); - import_map.insert_wildcard_alias("react/", ImportMapping::External(None).into()); - import_map.insert_exact_alias("react-dom", ImportMapping::External(None).into()); - import_map.insert_wildcard_alias("react-dom/", ImportMapping::External(None).into()); - import_map.insert_exact_alias("styled-jsx", ImportMapping::External(None).into()); - import_map.insert_wildcard_alias("styled-jsx/", ImportMapping::External(None).into()); + import_map.insert_exact_alias("next", external); + import_map.insert_wildcard_alias("next/", external); + import_map.insert_exact_alias("react", external); + import_map.insert_wildcard_alias("react/", external); + import_map.insert_exact_alias("react-dom", external); + import_map.insert_wildcard_alias("react-dom/", external); + import_map.insert_exact_alias("styled-jsx", external); + import_map.insert_wildcard_alias("styled-jsx/", external); } ServerContextType::AppSSR { .. } | ServerContextType::AppRSC { .. } | ServerContextType::AppRoute { .. } => { - for external in next_config.server_component_externals().await?.iter() { - import_map.insert_exact_alias(external, ImportMapping::External(None).into()); - import_map.insert_wildcard_alias( - format!("{external}/"), - ImportMapping::External(None).into(), - ); + for name in next_config.server_component_externals().await?.iter() { + import_map.insert_exact_alias(name, external); + import_map.insert_wildcard_alias(format!("{name}/"), external); } // The sandbox can't be bundled and needs to be external - import_map.insert_exact_alias( - "next/dist/server/web/sandbox", - ImportMapping::External(None).into(), - ); + import_map.insert_exact_alias("next/dist/server/web/sandbox", external); } ServerContextType::Middleware => {} } @@ -360,7 +355,7 @@ pub async fn insert_next_shared_aliases( import_map: &mut ImportMap, project_path: FileSystemPathVc, ) -> Result<()> { - let package_root = attached_next_js_package_path(project_path); + let package_root = next_js_fs().root(); // we use the next.js hydration code, so we replace the error overlay with our // own @@ -392,54 +387,38 @@ pub async fn insert_next_shared_aliases( ImportMapping::Dynamic(NextFontGoogleCssModuleReplacerVc::new(project_path).into()).into(), ); - import_map.insert_wildcard_alias( - "@swc/helpers/", - ImportMapping::PrimaryAlternative( - "./*".to_string(), - Some(get_swc_helpers_package(project_path)), - ) - .cell(), - ); + import_map.insert_singleton_alias("@swc/helpers", get_next_package(project_path)); + import_map.insert_singleton_alias("next", project_path); + import_map.insert_singleton_alias("react", project_path); + import_map.insert_singleton_alias("react-dom", project_path); Ok(()) } #[turbo_tasks::function] -fn package_lookup_resolve_options(project_root: FileSystemPathVc) -> ResolveOptionsVc { - resolve_options( - project_root, +async fn package_lookup_resolve_options( + project_path: FileSystemPathVc, +) -> Result { + Ok(resolve_options( + project_path, ResolveOptionsContext { - enable_node_modules: true, + enable_node_modules: Some(project_path.root().resolve().await?), enable_node_native_modules: true, custom_conditions: vec!["development".to_string()], ..Default::default() } .cell(), - ) + )) } #[turbo_tasks::function] -pub async fn get_next_package(project_root: FileSystemPathVc) -> Result { +pub async fn get_next_package(project_path: FileSystemPathVc) -> Result { let result = resolve( - project_root, + project_path, RequestVc::parse(Value::new(Pattern::Constant( "next/package.json".to_string(), ))), - package_lookup_resolve_options(project_root), - ); - let assets = result.primary_assets().await?; - let asset = assets.first().context("Next.js package not found")?; - Ok(asset.ident().path().parent()) -} - -#[turbo_tasks::function] -pub async fn get_swc_helpers_package(project_root: FileSystemPathVc) -> Result { - let result = resolve( - get_next_package(project_root), - RequestVc::parse(Value::new(Pattern::Constant( - "@swc/helpers/package.json".to_string(), - ))), - package_lookup_resolve_options(project_root), + package_lookup_resolve_options(project_path), ); let assets = result.primary_assets().await?; let asset = assets.first().context("Next.js package not found")?; diff --git a/crates/next-core/src/next_server/context.rs b/crates/next-core/src/next_server/context.rs index ea432214f61ee..82a3503c8da2a 100644 --- a/crates/next-core/src/next_server/context.rs +++ b/crates/next-core/src/next_server/context.rs @@ -27,7 +27,7 @@ use crate::{ babel::maybe_add_babel_loader, next_build::{get_external_next_compiled_package_mapping, get_postcss_package_mapping}, next_config::NextConfigVc, - next_import_map::{get_next_build_import_map, get_next_server_import_map}, + next_import_map::get_next_server_import_map, util::foreign_code_context_condition, }; @@ -50,6 +50,7 @@ pub async fn get_server_resolve_options_context( ) -> Result { let next_server_import_map = get_next_server_import_map(project_path, ty, next_config); let foreign_code_context_condition = foreign_code_context_condition(next_config).await?; + let root_dir = project_path.root().resolve().await?; Ok(match ty.into_value() { ServerContextType::Pages { .. } | ServerContextType::PagesData { .. } => { @@ -59,7 +60,7 @@ pub async fn get_server_resolve_options_context( ); let resolve_options_context = ResolveOptionsContext { - enable_node_modules: true, + enable_node_modules: Some(root_dir), enable_node_externals: true, enable_node_native_modules: true, module: true, @@ -80,7 +81,7 @@ pub async fn get_server_resolve_options_context( } ServerContextType::AppSSR { .. } => { let resolve_options_context = ResolveOptionsContext { - enable_node_modules: true, + enable_node_modules: Some(root_dir), enable_node_externals: true, enable_node_native_modules: true, module: true, @@ -100,7 +101,7 @@ pub async fn get_server_resolve_options_context( } ServerContextType::AppRSC { .. } => { let resolve_options_context = ResolveOptionsContext { - enable_node_modules: true, + enable_node_modules: Some(root_dir), enable_node_externals: true, enable_node_native_modules: true, module: true, @@ -120,7 +121,7 @@ pub async fn get_server_resolve_options_context( } ServerContextType::AppRoute { .. } => { let resolve_options_context = ResolveOptionsContext { - enable_node_modules: true, + enable_node_modules: Some(root_dir), module: true, custom_conditions: vec!["development".to_string()], import_map: Some(next_server_import_map), @@ -138,7 +139,7 @@ pub async fn get_server_resolve_options_context( } ServerContextType::Middleware => { let resolve_options_context = ResolveOptionsContext { - enable_node_modules: true, + enable_node_modules: Some(root_dir), enable_node_externals: true, module: true, custom_conditions: vec!["development".to_string()], @@ -327,23 +328,6 @@ pub async fn get_server_module_options_context( Ok(module_options_context) } -#[turbo_tasks::function] -pub fn get_build_resolve_options_context( - project_path: FileSystemPathVc, -) -> ResolveOptionsContextVc { - let next_build_import_map = get_next_build_import_map(project_path); - ResolveOptionsContext { - enable_typescript: true, - enable_node_modules: true, - enable_node_externals: true, - enable_node_native_modules: true, - custom_conditions: vec!["development".to_string()], - import_map: Some(next_build_import_map), - ..Default::default() - } - .cell() -} - #[turbo_tasks::function] pub fn get_build_module_options_context() -> ModuleOptionsContextVc { ModuleOptionsContext { diff --git a/crates/next-core/src/page_loader.rs b/crates/next-core/src/page_loader.rs index 56c86298e1073..8c766c71f01e2 100644 --- a/crates/next-core/src/page_loader.rs +++ b/crates/next-core/src/page_loader.rs @@ -1,8 +1,8 @@ use std::io::Write; use anyhow::{bail, Result}; -use serde_json::Value; -use turbo_tasks::primitives::StringVc; +use indexmap::indexmap; +use turbo_tasks::{primitives::StringVc, Value}; use turbo_tasks_fs::{rope::RopeBuilder, File, FileContent, FileSystemPathVc}; use turbopack_core::{ asset::{Asset, AssetContentVc, AssetVc}, @@ -10,15 +10,16 @@ use turbopack_core::{ context::{AssetContext, AssetContextVc}, ident::AssetIdentVc, reference::AssetReferencesVc, + reference_type::{EntryReferenceSubType, ReferenceType}, virtual_asset::VirtualAssetVc, }; use turbopack_dev_server::source::{asset_graph::AssetGraphContentSourceVc, ContentSourceVc}; use turbopack_ecmascript::{ utils::stringify_js, EcmascriptInputTransform, EcmascriptInputTransformsVc, - EcmascriptModuleAssetType, EcmascriptModuleAssetVc, + EcmascriptModuleAssetType, EcmascriptModuleAssetVc, InnerAssetsVc, }; -use crate::{embed_js::next_js_file, util::get_asset_path_from_route}; +use crate::{embed_js::next_js_file_path, util::get_asset_path_from_route}; #[turbo_tasks::function] pub async fn create_page_loader( @@ -62,7 +63,8 @@ impl PageLoaderAssetVc { stringify_js(&format!("/{}", &*this.pathname.await?)) )?; - let base_code = next_js_file("entry/page-loader.ts"); + let page_loader_path = next_js_file_path("entry/page-loader.ts"); + let base_code = page_loader_path.read(); if let FileContent::Content(base_file) = &*base_code.await? { result += base_file.content() } else { @@ -71,11 +73,7 @@ impl PageLoaderAssetVc { let file = File::from(result.build()); - Ok(VirtualAssetVc::new( - this.entry_asset.ident().path().join("page-loader.ts"), - file.into(), - ) - .into()) + Ok(VirtualAssetVc::new(page_loader_path, file.into()).into()) } #[turbo_tasks::function] @@ -84,12 +82,15 @@ impl PageLoaderAssetVc { let loader_entry_asset = self.get_loader_entry_asset(); - let asset = EcmascriptModuleAssetVc::new( + let asset = EcmascriptModuleAssetVc::new_with_inner_assets( loader_entry_asset, this.client_context, - turbo_tasks::Value::new(EcmascriptModuleAssetType::Typescript), + Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), this.client_context.compile_time_info(), + InnerAssetsVc::cell(indexmap! { + "PAGE".to_string() => this.client_context.process(this.entry_asset, Value::new(ReferenceType::Entry(EntryReferenceSubType::Page))) + }), ); let chunk_group = @@ -119,13 +120,13 @@ impl Asset for PageLoaderAsset { let mut data = Vec::with_capacity(chunks.len()); for chunk in chunks.iter() { let path = chunk.path().await?; - data.push(Value::String(path.path.clone())); + data.push(serde_json::Value::String(path.path.clone())); } let content = format!( "__turbopack_load_page_chunks__({}, {})\n", stringify_js(&this.pathname.await?), - Value::Array(data) + serde_json::Value::Array(data) ); Ok(AssetContentVc::from(File::from(content))) diff --git a/crates/next-core/src/page_source.rs b/crates/next-core/src/page_source.rs index f3f13aa987dfa..cfe160afad926 100644 --- a/crates/next-core/src/page_source.rs +++ b/crates/next-core/src/page_source.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use indexmap::indexmap; use serde::{Deserialize, Serialize}; use turbo_tasks::{ primitives::{StringVc, StringsVc}, @@ -9,13 +10,12 @@ use turbo_tasks_env::ProcessEnvVc; use turbo_tasks_fs::{rebase, FileContent, FileSystemPathVc}; use turbopack::{transition::TransitionsByNameVc, ModuleAssetContextVc}; use turbopack_core::{ - asset::{Asset, AssetVc}, + asset::AssetVc, chunk::{dev::DevChunkingContextVc, ChunkingContextVc}, context::{AssetContext, AssetContextVc}, environment::{EnvironmentIntention, ServerAddrVc}, reference_type::{EntryReferenceSubType, ReferenceType}, source_asset::SourceAssetVc, - virtual_asset::VirtualAssetVc, }; use turbopack_dev_server::{ html::DevHtmlAssetVc, @@ -28,7 +28,7 @@ use turbopack_dev_server::{ }; use turbopack_ecmascript::{ chunk::EcmascriptChunkPlaceablesVc, EcmascriptInputTransform, EcmascriptInputTransformsVc, - EcmascriptModuleAssetType, EcmascriptModuleAssetVc, + EcmascriptModuleAssetType, EcmascriptModuleAssetVc, InnerAssetsVc, }; use turbopack_env::ProcessEnvAssetVc; use turbopack_node::{ @@ -41,7 +41,7 @@ use turbopack_node::{ }; use crate::{ - embed_js::{attached_next_js_package_path, next_asset, next_js_file, wrap_with_next_js_fs}, + embed_js::{next_asset, next_js_file}, env::env_for_js, fallback::get_fallback_page, next_client::{ @@ -78,7 +78,7 @@ use crate::{ #[turbo_tasks::function] pub async fn create_page_source( pages_structure: OptionPagesStructureVc, - project_root: FileSystemPathVc, + project_path: FileSystemPathVc, execution_context: ExecutionContextVc, output_path: FileSystemPathVc, server_root: FileSystemPathVc, @@ -87,8 +87,6 @@ pub async fn create_page_source( next_config: NextConfigVc, server_addr: ServerAddrVc, ) -> Result { - let project_path = wrap_with_next_js_fs(project_root); - let Some(pages_structure) = *pages_structure.await? else { return Ok(NoContentSourceVc::new().into()); }; @@ -476,10 +474,7 @@ async fn create_not_found_page_source( ( // The error page asset must be within the context path so it can depend on the // Next.js module. - next_asset( - attached_next_js_package_path(project_path).join("entry/error.tsx"), - "entry/error.tsx", - ), + next_asset("entry/error.tsx"), // If no 404 page is defined, the pathname should be _error. StringVc::cell("_error".to_string()), ) @@ -642,12 +637,12 @@ impl SsrEntryVc { #[turbo_tasks::function] async fn entry(self) -> Result { let this = self.await?; + let entry_asset_page = this.context.process( + this.entry_asset, + Value::new(ReferenceType::Entry(EntryReferenceSubType::Page)), + ); let ty = if this.ty == SsrType::AutoApi { - let entry_asset = this.context.process( - this.entry_asset, - Value::new(ReferenceType::Entry(EntryReferenceSubType::Page)), - ); - let page_config = parse_config_from_source(entry_asset); + let page_config = parse_config_from_source(entry_asset_page); if page_config.await?.runtime == NextRuntime::Edge { SsrType::EdgeApi } else { @@ -656,29 +651,52 @@ impl SsrEntryVc { } else { this.ty }; - let virtual_asset = match ty { + let (internal_asset, inner_assets) = match ty { SsrType::AutoApi => unreachable!(), - SsrType::Api => VirtualAssetVc::new( - this.entry_asset.ident().path().join("server-api.tsx"), - next_js_file("entry/server-api.tsx").into(), - ), - SsrType::EdgeApi => VirtualAssetVc::new( - this.entry_asset.ident().path().join("server-edge-api.tsx"), - next_js_file("entry/server-edge-api.tsx").into(), - ), - SsrType::Data => VirtualAssetVc::new( - this.entry_asset.ident().path().join("server-data.tsx"), - next_js_file("entry/server-data.tsx").into(), + SsrType::Api => ( + next_asset("entry/server-api.tsx"), + indexmap! { + "INNER".to_string() => entry_asset_page, + }, ), - SsrType::Html => VirtualAssetVc::new( - this.entry_asset.ident().path().join("server-renderer.tsx"), - next_js_file("entry/server-renderer.tsx").into(), + SsrType::EdgeApi => { + let entry_asset_edge_chunk_group = + this.context.with_transition("next-edge").process( + this.entry_asset, + Value::new(ReferenceType::Entry(EntryReferenceSubType::PagesApi)), + ); + ( + next_asset("entry/server-edge-api.tsx"), + indexmap! { + "INNER_EDGE_CHUNK_GROUP".to_string() => entry_asset_edge_chunk_group, + }, + ) + } + SsrType::Data => ( + next_asset("entry/server-data.tsx"), + indexmap! { + "INNER".to_string() => entry_asset_page, + }, ), + SsrType::Html => { + let entry_asset_client_chunk_group = + this.context.with_transition("next-client").process( + this.entry_asset, + Value::new(ReferenceType::Entry(EntryReferenceSubType::Page)), + ); + ( + next_asset("entry/server-renderer.tsx"), + indexmap! { + "INNER".to_string() => entry_asset_page, + "INNER_CLIENT_CHUNK_GROUP".to_string() => entry_asset_client_chunk_group, + }, + ) + } }; Ok(NodeRenderingEntry { - module: EcmascriptModuleAssetVc::new( - virtual_asset.into(), + module: EcmascriptModuleAssetVc::new_with_inner_assets( + internal_asset, this.context, Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![ @@ -686,6 +704,7 @@ impl SsrEntryVc { EcmascriptInputTransform::React { refresh: false }, ]), this.context.compile_time_info(), + InnerAssetsVc::cell(inner_assets), ), chunking_context: this.chunking_context, intermediate_output_path: this.intermediate_output_path, diff --git a/crates/next-core/src/pages_structure.rs b/crates/next-core/src/pages_structure.rs index fd8f824339f10..7a571929aac26 100644 --- a/crates/next-core/src/pages_structure.rs +++ b/crates/next-core/src/pages_structure.rs @@ -6,7 +6,7 @@ use turbo_tasks::{ use turbo_tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPathVc}; use turbopack_dev_server::source::specificity::SpecificityVc; -use crate::{embed_js::wrap_with_next_js_fs, next_config::NextConfigVc}; +use crate::next_config::NextConfigVc; /// A final route in the pages directory. #[turbo_tasks::value] @@ -113,8 +113,6 @@ pub async fn find_pages_structure( server_root: FileSystemPathVc, next_config: NextConfigVc, ) -> Result { - let project_path = wrap_with_next_js_fs(project_path); - let pages = project_path.join("pages"); let src_pages = project_path.join("src/pages"); let pages_dir = if *pages.get_type().await? == FileSystemEntryType::Directory { diff --git a/crates/next-core/src/router.rs b/crates/next-core/src/router.rs index b1de76441c1d4..498cac2bd06f6 100644 --- a/crates/next-core/src/router.rs +++ b/crates/next-core/src/router.rs @@ -1,5 +1,5 @@ use anyhow::{bail, Result}; -use indexmap::IndexMap; +use indexmap::indexmap; use serde::Deserialize; use serde_json::json; use turbo_tasks::{ @@ -33,7 +33,7 @@ use turbopack_node::{ }; use crate::{ - embed_js::{next_asset, next_js_file, wrap_with_next_js_fs}, + embed_js::{next_asset, next_js_file}, next_config::NextConfigVc, next_edge::{ context::{get_edge_compile_time_info, get_edge_resolve_options_context}, @@ -236,20 +236,16 @@ async fn config_assets( ) .as_asset(); - let mut inner = IndexMap::new(); - inner.insert("MIDDLEWARE_CHUNK_GROUP".to_string(), manifest); - inner.insert("MIDDLEWARE_CONFIG".to_string(), config_asset); - Ok(InnerAssetsVc::cell(inner)) + Ok(InnerAssetsVc::cell(indexmap! { + "MIDDLEWARE_CHUNK_GROUP".to_string() => manifest, + "MIDDLEWARE_CONFIG".to_string() => config_asset, + })) } #[turbo_tasks::function] -fn route_executor( - context: AssetContextVc, - project_path: FileSystemPathVc, - configs: InnerAssetsVc, -) -> AssetVc { +fn route_executor(context: AssetContextVc, configs: InnerAssetsVc) -> AssetVc { EcmascriptModuleAssetVc::new_with_inner_assets( - next_asset(project_path.join("router.js"), "entry/router.ts"), + next_asset("entry/router.ts"), context, Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), @@ -311,15 +307,15 @@ pub async fn route( routes_changed: CompletionVc, ) -> Result { let ExecutionContext { - project_root, + project_path, intermediate_output_path, env, } = *execution_context.await?; - let project_path = wrap_with_next_js_fs(project_root); let intermediate_output_path = intermediate_output_path.join("router"); let context = node_evaluate_asset_context( - Some(get_next_build_import_map(project_path)), + project_path, + Some(get_next_build_import_map()), Some(edge_transition_map( server_addr, project_path, @@ -329,21 +325,21 @@ pub async fn route( ); let configs = config_assets(context, project_path, next_config.page_extensions()); - let router_asset = route_executor(context, project_path, configs); + let router_asset = route_executor(context, configs); // TODO this is a hack to get these files watched. let next_config = watch_files_hack(context, project_path); let request = serde_json::value::to_value(&*request.await?)?; - let Some(dir) = to_sys_path(project_root).await? else { + let Some(dir) = to_sys_path(project_path).await? else { bail!("Next.js requires a disk path to check for valid routes"); }; let result = evaluate( project_path, router_asset, - project_root, + project_path, env, - AssetIdentVc::from_path(project_root), + AssetIdentVc::from_path(project_path), context, intermediate_output_path, Some(next_config), diff --git a/crates/next-core/src/router_source.rs b/crates/next-core/src/router_source.rs index de22d55e03e71..af77c78361fb8 100644 --- a/crates/next-core/src/router_source.rs +++ b/crates/next-core/src/router_source.rs @@ -77,7 +77,7 @@ impl ContentSource for NextRouterContentSource { // The next-dev server can currently run against projects as simple as // `index.js`. If this isn't a Next.js project, don't try to use the Next.js // router. - let project_root = this.execution_context.await?.project_root; + let project_root = this.execution_context.await?.project_path; if !(*has_next_config(project_root).await?) { return Ok(this .inner diff --git a/crates/next-core/src/web_entry_source.rs b/crates/next-core/src/web_entry_source.rs index 9e5449d2c46f9..7655536cae7b4 100644 --- a/crates/next-core/src/web_entry_source.rs +++ b/crates/next-core/src/web_entry_source.rs @@ -15,7 +15,6 @@ use turbopack_dev_server::{ use turbopack_node::execution_context::ExecutionContextVc; use crate::{ - embed_js::wrap_with_next_js_fs, next_client::context::{ get_client_asset_context, get_client_chunking_context, get_client_compile_time_info, get_client_runtime_entries, ClientContextType, @@ -25,7 +24,7 @@ use crate::{ #[turbo_tasks::function] pub async fn create_web_entry_source( - project_root: FileSystemPathVc, + project_path: FileSystemPathVc, execution_context: ExecutionContextVc, entry_requests: Vec, server_root: FileSystemPathVc, @@ -34,28 +33,26 @@ pub async fn create_web_entry_source( browserslist_query: &str, next_config: NextConfigVc, ) -> Result { - let project_root = wrap_with_next_js_fs(project_root); - let ty = Value::new(ClientContextType::Other); let compile_time_info = get_client_compile_time_info(browserslist_query); let context = get_client_asset_context( - project_root, + project_path, execution_context, compile_time_info, ty, next_config, ); let chunking_context = get_client_chunking_context( - project_root, + project_path, server_root, compile_time_info.environment(), ty, ); - let entries = get_client_runtime_entries(project_root, env, ty, next_config); + let entries = get_client_runtime_entries(project_path, env, ty, next_config); let runtime_entries = entries.resolve_entries(context); - let origin = PlainResolveOriginVc::new(context, project_root.join("_")).as_resolve_origin(); + let origin = PlainResolveOriginVc::new(context, project_path.join("_")).as_resolve_origin(); let entries = entry_requests .into_iter() .map(|request| async move { diff --git a/crates/next-dev-tests/tests/integration/next/font-google/at-next-font/input/pages/index.js b/crates/next-dev-tests/tests/integration/next/font-google/at-next-font/input/pages/index.js index 23da4f858db11..cc4ced575de1b 100644 --- a/crates/next-dev-tests/tests/integration/next/font-google/at-next-font/input/pages/index.js +++ b/crates/next-dev-tests/tests/integration/next/font-google/at-next-font/input/pages/index.js @@ -15,7 +15,7 @@ export default function Home() { function runTests() { it("continues to be able to import from `@next/font/google`", () => { expect(interNoArgs).toEqual({ - className: "className__inter_34ab8b4d__318bf44f", + className: "className__inter_34ab8b4d__7bdff866", style: { fontFamily: "'__Inter_34ab8b4d'", fontStyle: "normal", diff --git a/crates/next-dev-tests/tests/integration/next/font-google/basic/input/pages/index.js b/crates/next-dev-tests/tests/integration/next/font-google/basic/input/pages/index.js index aa4c32f10d251..1d2ff61decdc9 100644 --- a/crates/next-dev-tests/tests/integration/next/font-google/basic/input/pages/index.js +++ b/crates/next-dev-tests/tests/integration/next/font-google/basic/input/pages/index.js @@ -18,7 +18,7 @@ export default function Home() { function runTests() { it("returns structured data about the font styles from the font function", () => { expect(interNoArgs).toEqual({ - className: "className__inter_34ab8b4d__64ed1f97", + className: "className__inter_34ab8b4d__7bdff866", style: { fontFamily: "'__Inter_34ab8b4d'", fontStyle: "normal", @@ -35,12 +35,12 @@ function runTests() { it("supports declaring a css custom property (css variable)", async () => { expect(interWithVariableName).toEqual({ - className: "className__inter_c6e282f1__a8cc5613", + className: "className__inter_c6e282f1__e152ac0c", style: { fontFamily: "'__Inter_c6e282f1'", fontStyle: "normal", }, - variable: "variable__inter_c6e282f1__a8cc5613", + variable: "variable__inter_c6e282f1__e152ac0c", }); const matchingRule = await getRuleMatchingClassName( diff --git a/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-c19e79.txt b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-5efef4.txt similarity index 77% rename from crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-c19e79.txt rename to crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-5efef4.txt index 2a3d74a7da29d..8eea1e7d94059 100644 --- a/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-c19e79.txt +++ b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-5efef4.txt @@ -1,6 +1,6 @@ PlainIssue { severity: Warning, - context: "[project-with-next]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", + context: "[project]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", category: "parse", title: "lint TP1004 fs.existsSync(???*0*) is very dynamic", description: "- *0* arguments[0]\n ⚠\u{fe0f} function calls are not analysed yet", @@ -9,7 +9,7 @@ PlainIssue { source: Some( PlainIssueSource { asset: PlainAsset { - ident: "[project-with-next]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", + ident: "[project]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", }, start: SourcePos { line: 87, @@ -22,4 +22,4 @@ PlainIssue { }, ), sub_issues: [], -} +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-58d7af.txt b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-f84517.txt similarity index 77% rename from crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-58d7af.txt rename to crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-f84517.txt index ce511030f3b65..6dc6703ee92a3 100644 --- a/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-58d7af.txt +++ b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-f84517.txt @@ -1,6 +1,6 @@ PlainIssue { severity: Warning, - context: "[project-with-next]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", + context: "[project]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", category: "parse", title: "lint TP1004 fs.readFileSync(???*0*, \"utf-8\") is very dynamic", description: "- *0* arguments[0]\n ⚠\u{fe0f} function calls are not analysed yet", @@ -9,7 +9,7 @@ PlainIssue { source: Some( PlainIssueSource { asset: PlainAsset { - ident: "[project-with-next]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", + ident: "[project]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", }, start: SourcePos { line: 89, @@ -22,4 +22,4 @@ PlainIssue { }, ), sub_issues: [], -} +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-667243.txt b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-dd45bc.txt similarity index 78% rename from crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-667243.txt rename to crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-dd45bc.txt index 7ffaf6bf482b4..d5b11a8683725 100644 --- a/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-667243.txt +++ b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-dd45bc.txt @@ -1,6 +1,6 @@ PlainIssue { severity: Warning, - context: "[project-with-next]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/input.js", + context: "[project]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/input.js", category: "parse", title: "lint TP1006 path.resolve(???*0*) is very dynamic", description: "- *0* ???*1*[\"from\"]\n ⚠\u{fe0f} unknown object\n- *1* opts\n ⚠\u{fe0f} pattern without value", @@ -9,7 +9,7 @@ PlainIssue { source: Some( PlainIssueSource { asset: PlainAsset { - ident: "[project-with-next]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/input.js", + ident: "[project]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/input.js", }, start: SourcePos { line: 43, @@ -22,4 +22,4 @@ PlainIssue { }, ), sub_issues: [], -} +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error evaluating Node.js code-28e1f2.txt b/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error evaluating Node.js code-bf8568.txt similarity index 77% rename from crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error evaluating Node.js code-28e1f2.txt rename to crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error evaluating Node.js code-bf8568.txt index 4fd66e4be21b5..3e60ddadf87a7 100644 --- a/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error evaluating Node.js code-28e1f2.txt +++ b/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error evaluating Node.js code-bf8568.txt @@ -3,7 +3,7 @@ PlainIssue { context: "[project]/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input", category: "build", title: "Error evaluating Node.js code", - description: "Error: > Couldn't find a `pages` directory. Please create one under the project root\n at Object.findPagesDir (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/lib/find-pages-dir.js:86:19)\n at DevServer.getRoutes (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/dev/next-dev-server.js:130:59)\n at new Server (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/base-server.js:108:47)\n at new NextNodeServer (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/next-server.js:69:9)\n at new DevServer (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/dev/next-dev-server.js:96:9)\n at Object.makeResolver (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/lib/route-resolver.js:39:23)\n at getResolveRoute (crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/.next/build/router/chunks/router_f8de3f.js:173:109)\n at async Module.route (crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/.next/build/router/chunks/router_f8de3f.js:179:36)\n at async Module.run (crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/.next/build/router/chunks/[turbopack-node]_ipc_evaluate.ts._.js:142:39)\n", + description: "Error: > Couldn't find a `pages` directory. Please create one under the project root\n at Object.findPagesDir (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/lib/find-pages-dir.js:86:19)\n at DevServer.getRoutes (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/dev/next-dev-server.js:130:59)\n at new Server (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/base-server.js:108:47)\n at new NextNodeServer (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/next-server.js:69:9)\n at new DevServer (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/dev/next-dev-server.js:96:9)\n at Object.makeResolver (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/lib/route-resolver.js:39:23)\n at getResolveRoute (crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/.next/build/router/chunks/[next]_entry_router.ts_752f59._.js:30:109)\n at async Module.route (crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/.next/build/router/chunks/[next]_entry_router.ts_752f59._.js:36:36)\n at async Module.run (crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/.next/build/router/chunks/[turbopack-node]_ipc_evaluate.ts._.js:142:39)\n", detail: "", documentation_link: "", source: None, diff --git a/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error resolving commonjs request-6b96ad.txt b/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error resolving commonjs request-e56948.txt similarity index 52% rename from crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error resolving commonjs request-6b96ad.txt rename to crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error resolving commonjs request-e56948.txt index 05cbde4138bc6..d16398e3da94b 100644 --- a/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error resolving commonjs request-6b96ad.txt +++ b/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error resolving commonjs request-e56948.txt @@ -1,10 +1,10 @@ PlainIssue { severity: Error, - context: "[project-with-next]/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/index.js", + context: "[project]/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/index.js", category: "resolve", title: "Error resolving commonjs request", description: "unable to resolve relative \"./not-existing-file\"", - detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./not-existing-file\"\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./not-existing-file\"\nPath where resolving has started: [project]/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", documentation_link: "", source: None, sub_issues: [], diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-431056.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-6adb45.txt similarity index 50% rename from crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-431056.txt rename to crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-6adb45.txt index 12b6a9c3d414e..55df2e44d15b1 100644 --- a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-431056.txt +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-6adb45.txt @@ -1,10 +1,10 @@ PlainIssue { severity: Error, - context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js", + context: "[project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js", category: "resolve", title: "Error resolving EcmaScript Modules request", description: "unable to resolve relative \"./empty?import1-in-chunk1\"", - detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?import1-in-chunk1\"\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js\nType of request: EcmaScript Modules request\nImport map: No import map entry\n", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?import1-in-chunk1\"\nPath where resolving has started: [project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js\nType of request: EcmaScript Modules request\nImport map: No import map entry\n", documentation_link: "", source: None, sub_issues: [], diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-1a1150.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-d56c20.txt similarity index 50% rename from crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-1a1150.txt rename to crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-d56c20.txt index cd5c8c3160753..aa2e87a241931 100644 --- a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-1a1150.txt +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-d56c20.txt @@ -1,10 +1,10 @@ PlainIssue { severity: Error, - context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js", + context: "[project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js", category: "resolve", title: "Error resolving EcmaScript Modules request", description: "unable to resolve relative \"./empty?import2-in-chunk1\"", - detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?import2-in-chunk1\"\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js\nType of request: EcmaScript Modules request\nImport map: No import map entry\n", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?import2-in-chunk1\"\nPath where resolving has started: [project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js\nType of request: EcmaScript Modules request\nImport map: No import map entry\n", documentation_link: "", source: None, sub_issues: [], diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-a3050d.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-eb66f2.txt similarity index 50% rename from crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-a3050d.txt rename to crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-eb66f2.txt index 7bf04d0b03b36..0a5132b1984d0 100644 --- a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-a3050d.txt +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-eb66f2.txt @@ -1,10 +1,10 @@ PlainIssue { severity: Error, - context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js", + context: "[project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js", category: "resolve", title: "Error resolving EcmaScript Modules request", description: "unable to resolve relative \"./empty?import3-in-chunk2\"", - detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?import3-in-chunk2\"\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js\nType of request: EcmaScript Modules request\nImport map: No import map entry\n", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?import3-in-chunk2\"\nPath where resolving has started: [project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js\nType of request: EcmaScript Modules request\nImport map: No import map entry\n", documentation_link: "", source: None, sub_issues: [], diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/issues/Error resolving commonjs request-92a826.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/issues/Error resolving commonjs request-d35c6e.txt similarity index 51% rename from crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/issues/Error resolving commonjs request-92a826.txt rename to crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/issues/Error resolving commonjs request-d35c6e.txt index a1e0386bd6a3f..c28c72870bbae 100644 --- a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/issues/Error resolving commonjs request-92a826.txt +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/issues/Error resolving commonjs request-d35c6e.txt @@ -1,10 +1,10 @@ PlainIssue { severity: Error, - context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/input/index.js", + context: "[project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/input/index.js", category: "resolve", title: "Error resolving commonjs request", description: "unable to resolve relative \"./empty?require.ensure:test\"", - detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?require.ensure:test\"\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?require.ensure:test\"\nPath where resolving has started: [project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", documentation_link: "", source: None, sub_issues: [], diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/Error resolving commonjs request-354825.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/Error resolving commonjs request-354825.txt deleted file mode 100644 index c7ffb33ad07b7..0000000000000 --- a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/Error resolving commonjs request-354825.txt +++ /dev/null @@ -1,11 +0,0 @@ -PlainIssue { - severity: Error, - context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js", - category: "resolve", - title: "Error resolving commonjs request", - description: "unable to resolve dynamic", - detail: "It was not possible to find the requested file.\nParsed request as written in source code: dynamic\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", - documentation_link: "", - source: None, - sub_issues: [], -} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/Error resolving commonjs request-86b73f.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/Error resolving commonjs request-d795f8.txt similarity index 50% rename from crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/Error resolving commonjs request-86b73f.txt rename to crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/Error resolving commonjs request-d795f8.txt index ecf350a66844a..21f2b4cb5d625 100644 --- a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/Error resolving commonjs request-86b73f.txt +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/Error resolving commonjs request-d795f8.txt @@ -1,10 +1,10 @@ PlainIssue { severity: Error, - context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js", + context: "[project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js", category: "resolve", title: "Error resolving commonjs request", description: "unable to resolve dynamic", - detail: "It was not possible to find the requested file.\nParsed request as written in source code: dynamic\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: dynamic\nPath where resolving has started: [project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", documentation_link: "", source: None, sub_issues: [], diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/lint TP1002 require([__quo__.__b__quo__]) is very dynamic-8bc115.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/lint TP1002 require([__quo__.__b__quo__]) is very dynamic-1b7b2d.txt similarity index 72% rename from crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/lint TP1002 require([__quo__.__b__quo__]) is very dynamic-8bc115.txt rename to crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/lint TP1002 require([__quo__.__b__quo__]) is very dynamic-1b7b2d.txt index fedb9cdda6f6f..f67dfec901570 100644 --- a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/lint TP1002 require([__quo__.__b__quo__]) is very dynamic-8bc115.txt +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/lint TP1002 require([__quo__.__b__quo__]) is very dynamic-1b7b2d.txt @@ -1,6 +1,6 @@ PlainIssue { severity: Warning, - context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js", + context: "[project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js", category: "parse", title: "lint TP1002 require([\"./b\"]) is very dynamic", description: "", @@ -9,7 +9,7 @@ PlainIssue { source: Some( PlainIssueSource { asset: PlainAsset { - ident: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js", + ident: "[project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js", }, start: SourcePos { line: 13, @@ -22,4 +22,4 @@ PlainIssue { }, ), sub_issues: [], -} +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/Error resolving commonjs request-0baf48.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/Error resolving commonjs request-0baf48.txt new file mode 100644 index 0000000000000..df46f9ef9d4de --- /dev/null +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/Error resolving commonjs request-0baf48.txt @@ -0,0 +1,11 @@ +PlainIssue { + severity: Error, + context: "[project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js", + category: "resolve", + title: "Error resolving commonjs request", + description: "unable to resolve dynamic", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: dynamic\nPath where resolving has started: [project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", + documentation_link: "", + source: None, + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/lint TP1002 require([__quo__.__c__quo__]) is very dynamic-80ea5a.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/lint TP1002 require([__quo__.__c__quo__]) is very dynamic-c9f4f1.txt similarity index 73% rename from crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/lint TP1002 require([__quo__.__c__quo__]) is very dynamic-80ea5a.txt rename to crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/lint TP1002 require([__quo__.__c__quo__]) is very dynamic-c9f4f1.txt index 981db21b950d5..ff2f926d2d096 100644 --- a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/lint TP1002 require([__quo__.__c__quo__]) is very dynamic-80ea5a.txt +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/lint TP1002 require([__quo__.__c__quo__]) is very dynamic-c9f4f1.txt @@ -1,6 +1,6 @@ PlainIssue { severity: Warning, - context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js", + context: "[project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js", category: "parse", title: "lint TP1002 require([\"./c\"]) is very dynamic", description: "", @@ -9,7 +9,7 @@ PlainIssue { source: Some( PlainIssueSource { asset: PlainAsset { - ident: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js", + ident: "[project]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js", }, start: SourcePos { line: 5, @@ -22,4 +22,4 @@ PlainIssue { }, ), sub_issues: [], -} +} \ No newline at end of file diff --git a/crates/turbopack-core/src/reference_type.rs b/crates/turbopack-core/src/reference_type.rs index 4b23764f53014..fb95e7c1f33fd 100644 --- a/crates/turbopack-core/src/reference_type.rs +++ b/crates/turbopack-core/src/reference_type.rs @@ -50,7 +50,10 @@ pub enum TypeScriptReferenceSubType { pub enum EntryReferenceSubType { Web, Page, + PagesApi, + AppPage, AppRoute, + AppClientComponent, Custom(u8), Undefined, } diff --git a/crates/turbopack-core/src/resolve/mod.rs b/crates/turbopack-core/src/resolve/mod.rs index 71b76d7e44f88..ecf196d4ff789 100644 --- a/crates/turbopack-core/src/resolve/mod.rs +++ b/crates/turbopack-core/src/resolve/mod.rs @@ -694,7 +694,7 @@ async fn resolve_internal( let result_ref = import_map.lookup(request).await?; let result = &*result_ref; if !matches!(result, ImportMapResult::NoEntry) { - let resolve_result_vc = + let resolved_result = resolve_import_map_result(result, context, context, request, options).await?; // We might have matched an alias in the import map, but there is no guarantee // the alias actually resolves to something. For instance, a tsconfig.json @@ -702,8 +702,8 @@ async fn resolve_internal( // would also match a request to "@emotion/core". Here, we follow what the // Typescript resolution algorithm does in case an alias match // doesn't resolve to anything: fall back to resolving the request normally. - if !*resolve_result_vc.is_unresolveable().await? { - return Ok(resolve_result_vc); + if let Some(result) = resolved_result { + return Ok(result); } } } @@ -844,10 +844,10 @@ async fn resolve_internal( if *result.is_unresolveable().await? { let result_ref = import_map.lookup(request).await?; let result = &*result_ref; - if !matches!(result, ImportMapResult::NoEntry) { - let resolve_result_vc = - resolve_import_map_result(result, context, context, request, options).await?; - return Ok(resolve_result_vc); + let resolved_result = + resolve_import_map_result(result, context, context, request, options).await?; + if let Some(result) = resolved_result { + return Ok(result); } } } @@ -1020,9 +1020,9 @@ async fn resolve_import_map_result( original_context: FileSystemPathVc, original_request: RequestVc, options: ResolveOptionsVc, -) -> Result { +) -> Result> { Ok(match result { - ImportMapResult::Result(result) => *result, + ImportMapResult::Result(result) => Some(*result), ImportMapResult::Alias(request, alias_context) => { let request = *request; let context = alias_context.unwrap_or(context); @@ -1030,18 +1030,9 @@ async fn resolve_import_map_result( if request.resolve().await? == original_request && context.resolve().await? == original_context { - let issue: ResolvingIssueVc = ResolvingIssue { - context: original_context, - request_type: format!("import map alias to {}", request.to_string().await?), - request: original_request, - resolve_options: options, - error_message: Some("cycle during resolving".to_string()), - } - .cell(); - issue.as_issue().emit(); - ResolveResult::unresolveable().cell() + None } else { - resolve_internal(context, request, options) + Some(resolve_internal(context, request, options)) } } ImportMapResult::Alternatives(list) => { @@ -1058,9 +1049,11 @@ async fn resolve_import_map_result( }) .try_join() .await?; - ResolveResultVc::select_first(results) + Some(ResolveResultVc::select_first( + results.into_iter().flatten().collect(), + )) } - ImportMapResult::NoEntry => unreachable!(), + ImportMapResult::NoEntry => None, }) } @@ -1070,7 +1063,7 @@ fn resolve_import_map_result_boxed<'a>( original_context: FileSystemPathVc, original_request: RequestVc, options: ResolveOptionsVc, -) -> Pin> + Send + 'a>> { +) -> Pin>> + Send + 'a>> { Box::pin(async move { resolve_import_map_result(result, context, original_context, original_request, options) .await @@ -1157,15 +1150,16 @@ async fn resolved( if let Some(resolved_map) = resolved_map { let result = resolved_map.lookup(*path, original_request).await?; - if !matches!(&*result, ImportMapResult::NoEntry) { - return resolve_import_map_result( - &result, - path.parent(), - original_context, - original_request, - options, - ) - .await; + let resolved_result = resolve_import_map_result( + &result, + path.parent(), + original_context, + original_request, + options, + ) + .await?; + if let Some(result) = resolved_result { + return Ok(result); } } diff --git a/crates/turbopack-core/src/resolve/options.rs b/crates/turbopack-core/src/resolve/options.rs index efe77b8c63d99..843c14b75bc65 100644 --- a/crates/turbopack-core/src/resolve/options.rs +++ b/crates/turbopack-core/src/resolve/options.rs @@ -206,6 +206,26 @@ impl ImportMap { self.map .insert(AliasPattern::wildcard(prefix, suffix), mapping); } + + /// Inserts an alias that resolves an prefix always from a certain location + /// to create a singleton. + pub fn insert_singleton_alias<'a>( + &mut self, + prefix: impl Into + 'a, + context_path: FileSystemPathVc, + ) { + let prefix = prefix.into(); + let wildcard_prefix = prefix.clone() + "/"; + let wildcard_alias: String = prefix.clone() + "/*"; + self.insert_exact_alias( + &prefix, + ImportMapping::PrimaryAlternative(prefix.clone(), Some(context_path)).cell(), + ); + self.insert_wildcard_alias( + wildcard_prefix, + ImportMapping::PrimaryAlternative(wildcard_alias, Some(context_path)).cell(), + ); + } } #[turbo_tasks::value_impl] diff --git a/crates/turbopack-ecmascript/src/chunk_group_files_asset.rs b/crates/turbopack-ecmascript/src/chunk_group_files_asset.rs index ad29e5864d34e..177275f28af5b 100644 --- a/crates/turbopack-ecmascript/src/chunk_group_files_asset.rs +++ b/crates/turbopack-ecmascript/src/chunk_group_files_asset.rs @@ -82,16 +82,18 @@ impl ChunkableAsset for ChunkGroupFilesAsset { #[turbo_tasks::value_impl] impl EcmascriptChunkPlaceable for ChunkGroupFilesAsset { #[turbo_tasks::function] - fn as_chunk_item( + async fn as_chunk_item( self_vc: ChunkGroupFilesAssetVc, context: ChunkingContextVc, - ) -> EcmascriptChunkItemVc { - ChunkGroupFilesChunkItem { + ) -> Result { + let this = self_vc.await?; + Ok(ChunkGroupFilesChunkItem { context, inner: self_vc, + chunk: this.asset.as_chunk(context), } .cell() - .into() + .into()) } #[turbo_tasks::function] @@ -104,6 +106,7 @@ impl EcmascriptChunkPlaceable for ChunkGroupFilesAsset { struct ChunkGroupFilesChunkItem { context: ChunkingContextVc, inner: ChunkGroupFilesAssetVc, + chunk: ChunkVc, } #[turbo_tasks::value_impl] diff --git a/crates/turbopack-node/src/evaluate.rs b/crates/turbopack-node/src/evaluate.rs index d7581fd910dca..06db28952129a 100644 --- a/crates/turbopack-node/src/evaluate.rs +++ b/crates/turbopack-node/src/evaluate.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, thread::available_parallelism, time::Duration}; use anyhow::{Context, Result}; use futures_retry::{FutureRetry, RetryPolicy}; -use indexmap::IndexMap; +use indexmap::indexmap; use turbo_tasks::{ primitives::{JsonValueVc, StringVc}, CompletionVc, TryJoinIterExt, Value, ValueToString, @@ -78,6 +78,8 @@ pub async fn get_evaluate_pool( let file_name = module_path.file_name(); let file_name = if file_name.ends_with(".js") { Cow::Borrowed(file_name) + } else if let Some(file_name) = file_name.strip_suffix(".ts") { + Cow::Owned(format!("{file_name}.js")) } else { Cow::Owned(format!("{file_name}.js")) }; @@ -96,10 +98,10 @@ pub async fn get_evaluate_pool( Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), context.compile_time_info(), - InnerAssetsVc::cell(IndexMap::from([ - ("INNER".to_string(), module_asset), - ("RUNTIME".to_string(), runtime_asset), - ])), + InnerAssetsVc::cell(indexmap! { + "INNER".to_string() => module_asset, + "RUNTIME".to_string() => runtime_asset + }), ); let (Some(cwd), Some(entrypoint)) = (to_sys_path(cwd).await?, to_sys_path(path).await?) else { diff --git a/crates/turbopack-node/src/execution_context.rs b/crates/turbopack-node/src/execution_context.rs index 86e4bbf2ccbc5..ce3986836f21d 100644 --- a/crates/turbopack-node/src/execution_context.rs +++ b/crates/turbopack-node/src/execution_context.rs @@ -4,7 +4,7 @@ use turbo_tasks_fs::FileSystemPathVc; #[turbo_tasks::value] pub struct ExecutionContext { - pub project_root: FileSystemPathVc, + pub project_path: FileSystemPathVc, pub intermediate_output_path: FileSystemPathVc, pub env: ProcessEnvVc, } @@ -13,12 +13,12 @@ pub struct ExecutionContext { impl ExecutionContextVc { #[turbo_tasks::function] pub fn new( - project_root: FileSystemPathVc, + project_path: FileSystemPathVc, intermediate_output_path: FileSystemPathVc, env: ProcessEnvVc, ) -> Self { ExecutionContext { - project_root, + project_path, intermediate_output_path, env, } @@ -29,9 +29,14 @@ impl ExecutionContextVc { pub async fn join(self, name: &str) -> Result { let this = self.await?; Ok(ExecutionContextVc::new( - this.project_root, + this.project_path, this.intermediate_output_path.join(name), this.env, )) } + + #[turbo_tasks::function] + pub async fn project_path(self) -> Result { + Ok(self.await?.project_path) + } } diff --git a/crates/turbopack-node/src/pool.rs b/crates/turbopack-node/src/pool.rs index b3d80ba75ef76..d4b3a129eb0af 100644 --- a/crates/turbopack-node/src/pool.rs +++ b/crates/turbopack-node/src/pool.rs @@ -176,11 +176,13 @@ impl NodeJsPoolProcess { match status { Ok(status) => { let (stdout, stderr) = get_output(&mut child).await?; + println!("node process exited before we could connect to it with {status}Process output:\n{stdout}\nProcess error output:\n{stderr}"); bail!("node process exited before we could connect to it with {status}\nProcess output:\n{stdout}\nProcess error output:\n{stderr}"); } Err(err) => { let _ = child.start_kill(); let (stdout, stderr) = get_output(&mut child).await?; + println!("node process exited before we could connect to it: {err:?}Process output:\n{stdout}\nProcess error output:\n{stderr}"); bail!("node process exited before we could connect to it: {err:?}\nProcess output:\n{stdout}\nProcess error output:\n{stderr}"); }, } @@ -188,6 +190,7 @@ impl NodeJsPoolProcess { _ = sleep(timeout) => { let _ = child.start_kill(); let (stdout, stderr) = get_output(&mut child).await?; + println!("timed out waiting for the Node.js process to connect ({timeout:?})Process output:\n{stdout}\nProcess error output:\n{stderr}"); bail!("timed out waiting for the Node.js process to connect ({timeout:?} timeout)\nProcess output:\n{stdout}\nProcess error output:\n{stderr}"); }, }; diff --git a/crates/turbopack-node/src/transforms/postcss.rs b/crates/turbopack-node/src/transforms/postcss.rs index 7789bdbdc181a..9418314fedc37 100644 --- a/crates/turbopack-node/src/transforms/postcss.rs +++ b/crates/turbopack-node/src/transforms/postcss.rs @@ -1,5 +1,5 @@ use anyhow::{bail, Context, Result}; -use indexmap::IndexMap; +use indexmap::indexmap; use serde::{Deserialize, Serialize}; use turbo_tasks::{ primitives::{JsonValueVc, StringsVc}, @@ -175,7 +175,9 @@ fn postcss_executor(context: AssetContextVc, postcss_config_path: FileSystemPath Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), context.compile_time_info(), - InnerAssetsVc::cell(IndexMap::from([("CONFIG".to_string(), config_asset)])), + InnerAssetsVc::cell(indexmap! { + "CONFIG".to_string() => config_asset + }), ) .into() } @@ -195,7 +197,7 @@ impl PostCssTransformedAssetVc { }; let ExecutionContext { - project_root, + project_path, intermediate_output_path, env, } = *this.execution_context.await?; @@ -219,9 +221,9 @@ impl PostCssTransformedAssetVc { let css_fs_path = this.source.ident().path().await?; let css_path = css_fs_path.path.as_str(); let config_value = evaluate( - project_root, + project_path, postcss_executor, - project_root, + project_path, env, this.source.ident(), context, diff --git a/crates/turbopack-node/src/transforms/webpack.rs b/crates/turbopack-node/src/transforms/webpack.rs index 08070c66acd22..37b88556b9c85 100644 --- a/crates/turbopack-node/src/transforms/webpack.rs +++ b/crates/turbopack-node/src/transforms/webpack.rs @@ -116,10 +116,10 @@ struct ProcessWebpackLoadersResult { } #[turbo_tasks::function] -fn webpack_loaders_executor(project_root: FileSystemPathVc, context: AssetContextVc) -> AssetVc { +fn webpack_loaders_executor(project_path: FileSystemPathVc, context: AssetContextVc) -> AssetVc { EcmascriptModuleAssetVc::new( VirtualAssetVc::new( - project_root.join("__turbopack__/webpack-loaders-executor.ts"), + project_path.join("__turbopack__/webpack-loaders-executor.ts"), AssetContent::File(embed_file("transforms/webpack-loaders.ts")).cell(), ) .into(), @@ -138,7 +138,7 @@ impl WebpackLoadersProcessedAssetVc { let this = self.await?; let ExecutionContext { - project_root, + project_path, intermediate_output_path, env, } = *this.execution_context.await?; @@ -155,14 +155,14 @@ impl WebpackLoadersProcessedAssetVc { let content = content.content().to_str()?; let context = this.evaluate_context; - let webpack_loaders_executor = webpack_loaders_executor(project_root, context); + let webpack_loaders_executor = webpack_loaders_executor(project_path, context); let resource_fs_path = this.source.ident().path().await?; let resource_path = resource_fs_path.path.as_str(); let loaders = this.loaders.await?; let config_value = evaluate( - project_root, + project_path, webpack_loaders_executor, - project_root, + project_path, env, this.source.ident(), context, diff --git a/crates/turbopack-tests/tests/snapshot.rs b/crates/turbopack-tests/tests/snapshot.rs index 0869a2811ae67..4f0d87616428b 100644 --- a/crates/turbopack-tests/tests/snapshot.rs +++ b/crates/turbopack-tests/tests/snapshot.rs @@ -206,12 +206,12 @@ async fn run_test(resource: String) -> Result { ResolveOptionsContext { enable_typescript: true, enable_react: true, - enable_node_modules: true, + enable_node_modules: Some(project_root), custom_conditions: vec!["development".to_string()], rules: vec![( ContextCondition::InDirectory("node_modules".to_string()), ResolveOptionsContext { - enable_node_modules: true, + enable_node_modules: Some(project_root), custom_conditions: vec!["development".to_string()], ..Default::default() } diff --git a/crates/turbopack/examples/turbopack.rs b/crates/turbopack/examples/turbopack.rs index b256fb3addd92..1df684a151e22 100644 --- a/crates/turbopack/examples/turbopack.rs +++ b/crates/turbopack/examples/turbopack.rs @@ -61,7 +61,7 @@ async fn main() -> Result<()> { ResolveOptionsContext { enable_typescript: true, enable_react: true, - enable_node_modules: true, + enable_node_modules: Some(fs.root()), custom_conditions: vec!["development".to_string()], ..Default::default() } diff --git a/crates/turbopack/src/evaluate_context.rs b/crates/turbopack/src/evaluate_context.rs index 66156eca1b99c..84ab4a6b4e2c1 100644 --- a/crates/turbopack/src/evaluate_context.rs +++ b/crates/turbopack/src/evaluate_context.rs @@ -1,4 +1,6 @@ +use anyhow::Result; use turbo_tasks::Value; +use turbo_tasks_fs::FileSystemPathVc; use turbopack_core::{ compile_time_defines, compile_time_info::CompileTimeInfo, @@ -13,11 +15,12 @@ use crate::{ }; #[turbo_tasks::function] -pub fn node_evaluate_asset_context( +pub async fn node_evaluate_asset_context( + project_path: FileSystemPathVc, import_map: Option, transitions: Option, -) -> AssetContextVc { - ModuleAssetContextVc::new( +) -> Result { + Ok(ModuleAssetContextVc::new( transitions.unwrap_or_else(|| TransitionsByNameVc::cell(Default::default())), CompileTimeInfo { environment: EnvironmentVc::new( @@ -40,7 +43,7 @@ pub fn node_evaluate_asset_context( .cell(), ResolveOptionsContext { enable_typescript: true, - enable_node_modules: true, + enable_node_modules: Some(project_path.root().resolve().await?), enable_node_externals: true, enable_node_native_modules: true, custom_conditions: vec!["development".to_string(), "node".to_string()], @@ -49,5 +52,5 @@ pub fn node_evaluate_asset_context( } .cell(), ) - .as_asset_context() + .as_asset_context()) } diff --git a/crates/turbopack/src/lib.rs b/crates/turbopack/src/lib.rs index 47d0336ce29e2..6cfc5f85764b8 100644 --- a/crates/turbopack/src/lib.rs +++ b/crates/turbopack/src/lib.rs @@ -160,100 +160,13 @@ async fn apply_module_type( }) } -#[turbo_tasks::function] -async fn module( - source: AssetVc, - context: ModuleAssetContextVc, - reference_type: Value, -) -> Result { - let ident = source.ident().resolve().await?; - let options = ModuleOptionsVc::new(ident.path().parent(), context.module_options_context()); - - let reference_type = reference_type.into_value(); - let mut current_source = source; - let mut current_module_type = None; - for rule in options.await?.rules.iter() { - if rule - .matches(source, &*ident.path().await?, &reference_type) - .await? - { - for effect in rule.effects() { - match effect { - ModuleRuleEffect::SourceTransforms(transforms) => { - current_source = transforms.transform(current_source); - if current_source.ident().resolve().await? != ident { - // The ident has been changed, so we need to apply new rules. - return Ok(module(current_source, context, Value::new(reference_type))); - } - } - ModuleRuleEffect::ModuleType(module) => { - current_module_type = Some(*module); - } - ModuleRuleEffect::AddEcmascriptTransforms(additional_transforms) => { - current_module_type = match current_module_type { - Some(ModuleType::Ecmascript(transforms)) => Some( - ModuleType::Ecmascript(transforms.extend(*additional_transforms)), - ), - Some(ModuleType::Typescript(transforms)) => Some( - ModuleType::Typescript(transforms.extend(*additional_transforms)), - ), - Some(ModuleType::TypescriptWithTypes(transforms)) => { - Some(ModuleType::TypescriptWithTypes( - transforms.extend(*additional_transforms), - )) - } - Some(module_type) => { - ModuleIssue { - ident, - title: StringVc::cell("Invalid module type".to_string()), - description: StringVc::cell( - "The module type must be Ecmascript or Typescript to add \ - Ecmascript transforms" - .to_string(), - ), - } - .cell() - .as_issue() - .emit(); - Some(module_type) - } - None => { - ModuleIssue { - ident, - title: StringVc::cell("Missing module type".to_string()), - description: StringVc::cell( - "The module type effect must be applied before adding \ - Ecmascript transforms" - .to_string(), - ), - } - .cell() - .as_issue() - .emit(); - None - } - }; - } - ModuleRuleEffect::Custom => { - todo!("Custom module rule effects are not yet supported"); - } - } - } - } - } - - let module_type = current_module_type.unwrap_or(ModuleType::Raw).cell(); - - Ok(apply_module_type(current_source, context, module_type)) -} - #[derive(Debug)] #[turbo_tasks::value] pub struct ModuleAssetContext { - transitions: TransitionsByNameVc, - compile_time_info: CompileTimeInfoVc, - module_options_context: ModuleOptionsContextVc, - resolve_options_context: ResolveOptionsContextVc, + pub transitions: TransitionsByNameVc, + pub compile_time_info: CompileTimeInfoVc, + pub module_options_context: ModuleOptionsContextVc, + pub resolve_options_context: ResolveOptionsContextVc, transition: Option, } @@ -323,6 +236,98 @@ impl ModuleAssetContextVc { resolve_options_context, )) } + + #[turbo_tasks::function] + async fn process_default( + self_vc: ModuleAssetContextVc, + source: AssetVc, + reference_type: Value, + ) -> Result { + let ident = source.ident().resolve().await?; + let options = ModuleOptionsVc::new(ident.path().parent(), self_vc.module_options_context()); + + let reference_type = reference_type.into_value(); + let mut current_source = source; + let mut current_module_type = None; + for rule in options.await?.rules.iter() { + if rule + .matches(source, &*ident.path().await?, &reference_type) + .await? + { + for effect in rule.effects() { + match effect { + ModuleRuleEffect::SourceTransforms(transforms) => { + current_source = transforms.transform(current_source); + if current_source.ident().resolve().await? != ident { + // The ident has been changed, so we need to apply new rules. + return Ok(self_vc + .process_default(current_source, Value::new(reference_type))); + } + } + ModuleRuleEffect::ModuleType(module) => { + current_module_type = Some(*module); + } + ModuleRuleEffect::AddEcmascriptTransforms(additional_transforms) => { + current_module_type = match current_module_type { + Some(ModuleType::Ecmascript(transforms)) => { + Some(ModuleType::Ecmascript( + transforms.extend(*additional_transforms), + )) + } + Some(ModuleType::Typescript(transforms)) => { + Some(ModuleType::Typescript( + transforms.extend(*additional_transforms), + )) + } + Some(ModuleType::TypescriptWithTypes(transforms)) => { + Some(ModuleType::TypescriptWithTypes( + transforms.extend(*additional_transforms), + )) + } + Some(module_type) => { + ModuleIssue { + ident, + title: StringVc::cell("Invalid module type".to_string()), + description: StringVc::cell( + "The module type must be Ecmascript or Typescript to \ + add Ecmascript transforms" + .to_string(), + ), + } + .cell() + .as_issue() + .emit(); + Some(module_type) + } + None => { + ModuleIssue { + ident, + title: StringVc::cell("Missing module type".to_string()), + description: StringVc::cell( + "The module type effect must be applied before adding \ + Ecmascript transforms" + .to_string(), + ), + } + .cell() + .as_issue() + .emit(); + None + } + }; + } + ModuleRuleEffect::Custom => { + todo!("Custom module rule effects are not yet supported"); + } + } + } + } + } + + let module_type = current_module_type.unwrap_or(ModuleType::Raw).cell(); + + Ok(apply_module_type(current_source, self_vc, module_type)) + } } #[turbo_tasks::value_impl] @@ -387,7 +392,6 @@ impl AssetContext for ModuleAssetContext { .await? .into()) } - #[turbo_tasks::function] async fn process( self_vc: ModuleAssetContextVc, @@ -396,28 +400,9 @@ impl AssetContext for ModuleAssetContext { ) -> Result { let this = self_vc.await?; if let Some(transition) = this.transition { - let asset = transition.process_source(asset); - let compile_time_info = transition.process_compile_time_info(this.compile_time_info); - let module_options_context = - transition.process_module_options_context(this.module_options_context); - let resolve_options_context = - transition.process_resolve_options_context(this.resolve_options_context); - let context = ModuleAssetContextVc::new( - this.transitions, - compile_time_info, - module_options_context, - resolve_options_context, - ); - let m = module(asset, context, reference_type); - Ok(transition.process_module(m, context)) + Ok(transition.process(asset, self_vc, reference_type)) } else { - let context = ModuleAssetContextVc::new( - this.transitions, - this.compile_time_info, - this.module_options_context, - this.resolve_options_context, - ); - Ok(module(asset, context, reference_type)) + Ok(self_vc.process_default(asset, reference_type)) } } diff --git a/crates/turbopack/src/module_options/mod.rs b/crates/turbopack/src/module_options/mod.rs index 62755c7a80864..012f734296570 100644 --- a/crates/turbopack/src/module_options/mod.rs +++ b/crates/turbopack/src/module_options/mod.rs @@ -153,7 +153,11 @@ impl ModuleOptionsVc { }; Some(ModuleRuleEffect::SourceTransforms( SourceTransformsVc::cell(vec![PostCssTransformVc::new( - node_evaluate_asset_context(Some(import_map), None), + node_evaluate_asset_context( + execution_context.project_path(), + Some(import_map), + None, + ), execution_context, ) .into()]), @@ -272,7 +276,11 @@ impl ModuleOptionsVc { ModuleRuleEffect::ModuleType(ModuleType::Ecmascript(app_transforms)), ModuleRuleEffect::SourceTransforms(SourceTransformsVc::cell(vec![ WebpackLoadersVc::new( - node_evaluate_asset_context(Some(import_map), None), + node_evaluate_asset_context( + execution_context.project_path(), + Some(import_map), + None, + ), execution_context, *loaders, ) diff --git a/crates/turbopack/src/resolve.rs b/crates/turbopack/src/resolve.rs index b335b2b1fe255..933c5406fec72 100644 --- a/crates/turbopack/src/resolve.rs +++ b/crates/turbopack/src/resolve.rs @@ -141,9 +141,9 @@ async fn base_resolve_options( } } else { let mut mods = Vec::new(); - if opt.enable_node_modules { + if let Some(dir) = opt.enable_node_modules { mods.push(ResolveModules::Nested( - root, + dir, vec!["node_modules".to_string()], )); } diff --git a/crates/turbopack/src/resolve_options_context.rs b/crates/turbopack/src/resolve_options_context.rs index ffae56b23ede9..2e7841053cec4 100644 --- a/crates/turbopack/src/resolve_options_context.rs +++ b/crates/turbopack/src/resolve_options_context.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use turbo_tasks_fs::FileSystemPathVc; use turbopack_core::{ environment::EnvironmentVc, resolve::{ @@ -17,7 +18,9 @@ pub struct ResolveOptionsContext { pub enable_typescript: bool, pub enable_react: bool, pub enable_node_native_modules: bool, - pub enable_node_modules: bool, + /// Enable resolving of the node_modules folder when withing the provided + /// directory + pub enable_node_modules: Option, /// Mark well-known Node.js modules as external imports and load them using /// native `require`. e.g. url, querystring, os pub enable_node_externals: bool, diff --git a/crates/turbopack/src/transition/mod.rs b/crates/turbopack/src/transition/mod.rs index 09ba9364b3a1c..2483cf556cef1 100644 --- a/crates/turbopack/src/transition/mod.rs +++ b/crates/turbopack/src/transition/mod.rs @@ -1,6 +1,10 @@ use std::collections::HashMap; -use turbopack_core::{asset::AssetVc, compile_time_info::CompileTimeInfoVc}; +use anyhow::Result; +use turbo_tasks::Value; +use turbopack_core::{ + asset::AssetVc, compile_time_info::CompileTimeInfoVc, reference_type::ReferenceType, +}; use crate::{ module_options::ModuleOptionsContextVc, resolve_options_context::ResolveOptionsContextVc, @@ -38,6 +42,37 @@ pub trait Transition { fn process_module(&self, asset: AssetVc, _context: ModuleAssetContextVc) -> AssetVc { asset } + /// Apply modifications to the context + async fn process_context( + self_vc: TransitionVc, + context: ModuleAssetContextVc, + ) -> Result { + let context = context.await?; + let compile_time_info = self_vc.process_compile_time_info(context.compile_time_info); + let module_options_context = + self_vc.process_module_options_context(context.module_options_context); + let resolve_options_context = + self_vc.process_resolve_options_context(context.resolve_options_context); + let context = ModuleAssetContextVc::new( + context.transitions, + compile_time_info, + module_options_context, + resolve_options_context, + ); + Ok(context) + } + /// Apply modification on the processing of the asset + fn process( + self_vc: TransitionVc, + asset: AssetVc, + context: ModuleAssetContextVc, + reference_type: Value, + ) -> AssetVc { + let asset = self_vc.process_source(asset); + let context = self_vc.process_context(context); + let m = context.process_default(asset, reference_type); + self_vc.process_module(m, context) + } } #[turbo_tasks::value(transparent)] diff --git a/crates/turbopack/tests/node-file-trace.rs b/crates/turbopack/tests/node-file-trace.rs index a4671f8c2fba6..3de910312d42b 100644 --- a/crates/turbopack/tests/node-file-trace.rs +++ b/crates/turbopack/tests/node-file-trace.rs @@ -420,7 +420,7 @@ fn node_file_trace( .cell(), ResolveOptionsContext { enable_node_native_modules: true, - enable_node_modules: true, + enable_node_modules: Some(input_dir), custom_conditions: vec!["node".to_string()], ..Default::default() }