From ab4597099bafeec1e126118eaa7c7eee91b88432 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Tue, 7 Feb 2023 23:56:06 +0100 Subject: [PATCH] refactor ResolveResult to allow mixing special and assets in alternatives (vercel/turbo#3675) Co-authored-by: Justin Ridgewell --- .../src/next_client_chunks/with_chunks.rs | 2 +- .../with_client_chunks.rs | 2 +- crates/next-core/src/next_font_google/mod.rs | 4 +- crates/next-core/src/next_server/resolve.rs | 4 +- crates/next-core/src/react_refresh.rs | 40 +-- crates/next-core/src/runtime.rs | 30 +- crates/turbopack-core/src/chunk/mod.rs | 51 +-- crates/turbopack-core/src/introspect/asset.rs | 7 +- crates/turbopack-core/src/reference/mod.rs | 39 +-- .../src/reference/source_map.rs | 13 +- crates/turbopack-core/src/resolve/mod.rs | 328 +++++++++--------- crates/turbopack-core/src/resolve/options.rs | 12 +- crates/turbopack-core/src/resolve/origin.rs | 2 +- crates/turbopack-css/src/asset.rs | 19 +- crates/turbopack-css/src/chunk/mod.rs | 12 +- crates/turbopack-css/src/chunk/source_map.rs | 2 +- crates/turbopack-css/src/module_asset.rs | 2 +- crates/turbopack-css/src/references/url.rs | 17 +- .../src/chunk/source_map.rs | 2 +- .../src/references/esm/base.rs | 41 ++- .../src/references/mod.rs | 41 ++- .../src/references/node.rs | 6 +- .../src/references/pattern_mapping.rs | 33 +- .../src/references/typescript.rs | 18 +- .../src/resolve/node_native_binding.rs | 42 ++- .../src/typescript/mod.rs | 2 +- .../src/typescript/resolve.rs | 4 +- .../turbopack-ecmascript/src/webpack/mod.rs | 23 +- .../src/render/rendered_source.rs | 11 +- 29 files changed, 401 insertions(+), 408 deletions(-) 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 b5290d713459f..ae552054a8afe 100644 --- a/crates/next-core/src/next_client_chunks/with_chunks.rs +++ b/crates/next-core/src/next_client_chunks/with_chunks.rs @@ -180,7 +180,7 @@ impl ValueToString for WithChunksAssetReference { impl AssetReference for WithChunksAssetReference { #[turbo_tasks::function] fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::Single(self.asset, Vec::new()).cell() + ResolveResult::asset(self.asset).cell() } } 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 696abb2e11cfc..253e4340539a5 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 @@ -189,7 +189,7 @@ impl ValueToString for WithClientChunksAssetReference { impl AssetReference for WithClientChunksAssetReference { #[turbo_tasks::function] fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::Single(self.asset, Vec::new()).cell() + ResolveResult::asset(self.asset).cell() } } diff --git a/crates/next-core/src/next_font_google/mod.rs b/crates/next-core/src/next_font_google/mod.rs index 6aef378d4923f..5929ed4171ef2 100644 --- a/crates/next-core/src/next_font_google/mod.rs +++ b/crates/next-core/src/next_font_google/mod.rs @@ -110,7 +110,7 @@ impl ImportMappingReplacement for NextFontGoogleReplacer { .into(), ); - Ok(ImportMapResult::Result(ResolveResult::Single(js_asset.into(), vec![]).into()).into()) + Ok(ImportMapResult::Result(ResolveResult::asset(js_asset.into()).into()).into()) } } @@ -227,7 +227,7 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer { .into(), ); - Ok(ImportMapResult::Result(ResolveResult::Single(css_asset.into(), vec![]).into()).into()) + Ok(ImportMapResult::Result(ResolveResult::asset(css_asset.into()).into()).into()) } } diff --git a/crates/next-core/src/next_server/resolve.rs b/crates/next-core/src/next_server/resolve.rs index 86be8764c7004..36bead596db13 100644 --- a/crates/next-core/src/next_server/resolve.rs +++ b/crates/next-core/src/next_server/resolve.rs @@ -5,7 +5,7 @@ use turbopack_core::resolve::{ find_context_file, package_json, parse::RequestVc, plugin::{ResolvePlugin, ResolvePluginConditionVc, ResolvePluginVc}, - FindContextFileResult, ResolveResult, ResolveResultOptionVc, SpecialType, + FindContextFileResult, PrimaryResolveResult, ResolveResult, ResolveResultOptionVc, }; #[turbo_tasks::value] @@ -91,7 +91,7 @@ impl ResolvePlugin for ExternalCjsModulesResolvePlugin { // mark as external Ok(ResolveResultOptionVc::some( - ResolveResult::Special(SpecialType::OriginalReferenceExternal, Vec::new()).cell(), + ResolveResult::primary(PrimaryResolveResult::OriginalReferenceExternal).cell(), )) } } diff --git a/crates/next-core/src/react_refresh.rs b/crates/next-core/src/react_refresh.rs index 6c74dfb156efa..618ec6f53ec83 100644 --- a/crates/next-core/src/react_refresh.rs +++ b/crates/next-core/src/react_refresh.rs @@ -10,7 +10,7 @@ use turbopack::{ }; use turbopack_core::{ issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}, - resolve::{origin::ResolveOriginVc, parse::RequestVc, ResolveResult}, + resolve::{origin::ResolveOriginVc, parse::RequestVc}, }; #[turbo_tasks::function] @@ -57,13 +57,10 @@ pub async fn assert_can_resolve_react_refresh( let resolve_options = apply_cjs_specific_options(turbopack::resolve_options(path, resolve_options_context)); for request in [react_refresh_request_in_next(), react_refresh_request()] { - let result = turbopack_core::resolve::resolve(path, request, resolve_options); + let result = turbopack_core::resolve::resolve(path, request, resolve_options).first_asset(); - match &*result.await? { - ResolveResult::Single(_, _) | ResolveResult::Alternatives(_, _) => { - return Ok(AssertReactRefreshResult::Found(request).cell()) - } - _ => {} + if result.await?.is_some() { + return Ok(AssertReactRefreshResult::Found(request).cell()); } } ReactRefreshResolvingIssue { @@ -82,26 +79,19 @@ pub async fn assert_can_resolve_react_refresh( /// Resolves the React Refresh runtime module from the given [AssetContextVc]. #[turbo_tasks::function] pub async fn resolve_react_refresh(origin: ResolveOriginVc) -> Result { - match &*cjs_resolve(origin, react_refresh_request()).await? { - ResolveResult::Single(asset, _) => { - if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? { - Ok(placeable) - } else { - Err(anyhow!("React Refresh runtime asset is not placeable")) - } + if let Some(asset) = *cjs_resolve(origin, react_refresh_request()) + .first_asset() + .await? + { + if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? { + Ok(placeable) + } else { + Err(anyhow!("React Refresh runtime asset is not placeable")) } - ResolveResult::Alternatives(assets, _) if !assets.is_empty() => { - if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(assets[0]).await? { - Ok(placeable) - } else { - Err(anyhow!("React Refresh runtime asset is not placeable")) - } - } - // The react-refresh-runtime module is not installed. - ResolveResult::Unresolveable(_) => Err(anyhow!( + } else { + Err(anyhow!( "could not resolve the `@next/react-refresh-utils/dist/runtime` module" - )), - _ => Err(anyhow!("invalid React Refresh runtime asset")), + )) } } diff --git a/crates/next-core/src/runtime.rs b/crates/next-core/src/runtime.rs index 039ed5c99c5e8..77c998e822ec6 100644 --- a/crates/next-core/src/runtime.rs +++ b/crates/next-core/src/runtime.rs @@ -1,6 +1,6 @@ -use anyhow::{anyhow, Result}; +use anyhow::{bail, Result}; use turbopack::ecmascript::{chunk::EcmascriptChunkPlaceableVc, resolve::cjs_resolve}; -use turbopack_core::resolve::{origin::ResolveOriginVc, parse::RequestVc, ResolveResult}; +use turbopack_core::resolve::{origin::ResolveOriginVc, parse::RequestVc}; /// Resolves the turbopack runtime module from the given [AssetContextVc]. #[turbo_tasks::function] @@ -11,26 +11,14 @@ pub async fn resolve_runtime_request( let runtime_request_path = format!("@vercel/turbopack-next/{}", path); let request = RequestVc::parse_string(runtime_request_path.clone()); - match &*cjs_resolve(origin, request).await? { - ResolveResult::Single(asset, _) => { - if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? { - Ok(placeable) - } else { - Err(anyhow!("turbopack runtime asset is not placeable")) - } - } - ResolveResult::Alternatives(assets, _) if !assets.is_empty() => { - if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(assets[0]).await? { - Ok(placeable) - } else { - Err(anyhow!("turbopack runtime asset is not placeable")) - } + if let Some(asset) = *cjs_resolve(origin, request).first_asset().await? { + if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? { + Ok(placeable) + } else { + bail!("turbopack runtime asset is not placeable") } + } else { // The @vercel/turbopack-runtime module is not installed. - ResolveResult::Unresolveable(_) => Err(anyhow!( - "could not resolve the `{}` module", - runtime_request_path - )), - _ => Err(anyhow!("invalid turbopack runtime asset")), + bail!("could not resolve the `{}` module", runtime_request_path) } } diff --git a/crates/turbopack-core/src/chunk/mod.rs b/crates/turbopack-core/src/chunk/mod.rs index b4c40deaa203d..b2b92cd07a8a8 100644 --- a/crates/turbopack-core/src/chunk/mod.rs +++ b/crates/turbopack-core/src/chunk/mod.rs @@ -23,7 +23,7 @@ use crate::{ asset::{Asset, AssetVc, AssetsVc}, environment::EnvironmentVc, reference::{AssetReference, AssetReferenceVc, AssetReferencesVc}, - resolve::{ResolveResult, ResolveResultVc}, + resolve::{PrimaryResolveResult, ResolveResult, ResolveResultVc}, }; /// A module id, which can be a number or string @@ -132,10 +132,16 @@ impl ChunkGroupVc { if *pc.is_loaded_in_parallel().await? { result = r .resolve_reference() - .primary_assets() .await? + .primary .iter() - .map(|r| async move { Ok(ChunkVc::resolve_from(r).await?) }) + .map(|r| async move { + Ok(if let PrimaryResolveResult::Asset(a) = r { + ChunkVc::resolve_from(a).await? + } else { + None + }) + }) .try_join() .await?; } @@ -270,7 +276,7 @@ impl ChunkReferenceVc { impl AssetReference for ChunkReference { #[turbo_tasks::function] fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::Single(self.chunk.into(), Vec::new()).into() + ResolveResult::asset(self.chunk.into()).into() } } @@ -318,7 +324,7 @@ impl AssetReference for ChunkGroupReference { .iter() .map(|c| c.as_asset()) .collect(); - Ok(ResolveResult::Alternatives(set, Vec::new()).into()) + Ok(ResolveResult::assets(set).into()) } } @@ -369,8 +375,8 @@ pub async fn chunk_content( enum ChunkContentWorkItem { AssetReferences(AssetReferencesVc), - Assets { - assets: AssetsVc, + ResolveResult { + result: ResolveResultVc, reference: AssetReferenceVc, chunking_type: ChunkingType, }, @@ -413,8 +419,8 @@ async fn chunk_content_internal( for r in item.await?.iter() { if let Some(pc) = ChunkableAssetReferenceVc::resolve_from(r).await? { if let Some(chunking_type) = *pc.chunking_type(context).await? { - queue.push_back(ChunkContentWorkItem::Assets { - assets: r.resolve_reference().primary_assets(), + queue.push_back(ChunkContentWorkItem::ResolveResult { + result: r.resolve_reference(), reference: *r, chunking_type, }); @@ -424,8 +430,8 @@ async fn chunk_content_internal( external_asset_references.push(*r); } } - ChunkContentWorkItem::Assets { - assets, + ChunkContentWorkItem::ResolveResult { + result, reference, chunking_type, } => { @@ -444,13 +450,16 @@ async fn chunk_content_internal( // not loaded in parallel let mut inner_chunk_groups = Vec::new(); - for asset in assets - .await? - .iter() - .filter(|asset| processed_assets.insert((chunking_type, **asset))) - { - let asset: &AssetVc = asset; - + let result = result.await?; + let assets = result.primary.iter().filter_map(|result| { + if let PrimaryResolveResult::Asset(asset) = *result { + if processed_assets.insert((chunking_type, asset)) { + return Some(asset); + } + } + None + }); + for asset in assets { let chunkable_asset = match ChunkableAssetVc::resolve_from(asset).await? { Some(chunkable_asset) => chunkable_asset, _ => { @@ -461,7 +470,7 @@ async fn chunk_content_internal( match chunking_type { ChunkingType::Placed => { - if let Some(chunk_item) = I::from_asset(context, *asset).await? { + if let Some(chunk_item) = I::from_asset(context, asset).await? { inner_chunk_items.push(chunk_item); } else { return Err(anyhow!( @@ -477,9 +486,9 @@ async fn chunk_content_internal( } ChunkingType::PlacedOrParallel => { // heuristic for being in the same chunk - if !split && *context.can_be_in_same_chunk(entry, *asset).await? { + if !split && *context.can_be_in_same_chunk(entry, asset).await? { // chunk item, chunk or other asset? - if let Some(chunk_item) = I::from_asset(context, *asset).await? { + if let Some(chunk_item) = I::from_asset(context, asset).await? { inner_chunk_items.push(chunk_item); continue; } diff --git a/crates/turbopack-core/src/introspect/asset.rs b/crates/turbopack-core/src/introspect/asset.rs index 7249c069bb10d..f2259160a13a8 100644 --- a/crates/turbopack-core/src/introspect/asset.rs +++ b/crates/turbopack-core/src/introspect/asset.rs @@ -8,6 +8,7 @@ use super::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}; use crate::{ asset::{Asset, AssetContent, AssetContentVc, AssetVc}, reference::{AssetReference, AssetReferencesVc}, + resolve::PrimaryResolveResult, }; #[turbo_tasks::value] @@ -83,8 +84,10 @@ pub async fn children_from_asset_references( let mut children = HashSet::new(); let references = references.await?; for reference in &*references { - for asset in &*reference.resolve_reference().primary_assets().await? { - children.insert((key, IntrospectableAssetVc::new(*asset))); + for result in reference.resolve_reference().await?.primary.iter() { + if let PrimaryResolveResult::Asset(asset) = result { + children.insert((key, IntrospectableAssetVc::new(*asset))); + } } } Ok(IntrospectableChildrenVc::cell(children)) diff --git a/crates/turbopack-core/src/reference/mod.rs b/crates/turbopack-core/src/reference/mod.rs index 2eecd8d7e8767..1f65aec51b2a1 100644 --- a/crates/turbopack-core/src/reference/mod.rs +++ b/crates/turbopack-core/src/reference/mod.rs @@ -6,11 +6,11 @@ use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; use crate::{ asset::{Asset, AssetVc, AssetsVc}, issue::IssueVc, - resolve::{ResolveResult, ResolveResultVc}, + resolve::{PrimaryResolveResult, ResolveResult, ResolveResultVc}, }; pub mod source_map; -pub use source_map::SourceMapVc; +pub use source_map::SourceMapReferenceVc; /// A reference to one or multiple [Asset]s or other special things. /// There are a bunch of optional traits that can influence how these references @@ -57,7 +57,7 @@ impl SingleAssetReference { impl AssetReference for SingleAssetReference { #[turbo_tasks::function] fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::Single(self.asset, vec![]).cell() + ResolveResult::asset(self.asset).cell() } } @@ -101,31 +101,18 @@ pub async fn all_referenced_assets(asset: AssetVc) -> Result { // while let Some(result) = race_pop(&mut queue).await { // match &*result? { while let Some(resolve_result) = queue.pop_front() { - match &*resolve_result.await? { - ResolveResult::Single(module, references) => { - assets.push(*module); - for reference in references { - queue.push_back(reference.resolve_reference()); - } - } - ResolveResult::Alternatives(modules, references) => { - assets.extend(modules); - for reference in references { - queue.push_back(reference.resolve_reference()); - } - } - ResolveResult::Special(_, references) => { - for reference in references { - queue.push_back(reference.resolve_reference()); - } - } - ResolveResult::Keyed(_, _) => todo!(), - ResolveResult::Unresolveable(references) => { - for reference in references { - queue.push_back(reference.resolve_reference()); - } + let ResolveResult { + primary, + references, + } = &*resolve_result.await?; + for result in primary { + if let PrimaryResolveResult::Asset(asset) = *result { + assets.push(asset); } } + for reference in references { + queue.push_back(reference.resolve_reference()); + } } Ok(AssetsVc::cell(assets)) } diff --git a/crates/turbopack-core/src/reference/source_map.rs b/crates/turbopack-core/src/reference/source_map.rs index ec82561eb6d44..0198ab4b03edc 100644 --- a/crates/turbopack-core/src/reference/source_map.rs +++ b/crates/turbopack-core/src/reference/source_map.rs @@ -9,28 +9,27 @@ use crate::{ }; #[turbo_tasks::value] -pub struct SourceMap { +pub struct SourceMapReference { from: FileSystemPathVc, file: FileSystemPathVc, } #[turbo_tasks::value_impl] -impl SourceMapVc { +impl SourceMapReferenceVc { #[turbo_tasks::function] pub fn new(from: FileSystemPathVc, file: FileSystemPathVc) -> Self { - Self::cell(SourceMap { from, file }) + Self::cell(SourceMapReference { from, file }) } } #[turbo_tasks::value_impl] -impl AssetReference for SourceMap { +impl AssetReference for SourceMapReference { #[turbo_tasks::function] async fn resolve_reference(&self) -> ResolveResultVc { let file_type = self.file.get_type().await; if let Ok(file_type_result) = file_type.as_ref() { if let FileSystemEntryType::File = &**file_type_result { - return ResolveResult::Single(SourceAssetVc::new(self.file).into(), Vec::new()) - .into(); + return ResolveResult::asset(SourceAssetVc::new(self.file).into()).into(); } } ResolveResult::unresolveable().into() @@ -38,7 +37,7 @@ impl AssetReference for SourceMap { } #[turbo_tasks::value_impl] -impl ValueToString for SourceMap { +impl ValueToString for SourceMapReference { #[turbo_tasks::function] async fn to_string(&self) -> Result { Ok(StringVc::cell(format!( diff --git a/crates/turbopack-core/src/resolve/mod.rs b/crates/turbopack-core/src/resolve/mod.rs index bfb4bc105a174..6fcdc11b3fa29 100644 --- a/crates/turbopack-core/src/resolve/mod.rs +++ b/crates/turbopack-core/src/resolve/mod.rs @@ -2,16 +2,13 @@ use std::{ borrow::Cow, collections::{BTreeMap, HashMap, HashSet}, future::Future, - mem::take, pin::Pin, }; use anyhow::{anyhow, Result}; -use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; use turbo_tasks::{ primitives::{BoolVc, StringVc, StringsVc}, - trace::TraceRawVcs, TryJoinIterExt, Value, ValueToString, ValueToStringVc, }; use turbo_tasks_fs::{ @@ -30,7 +27,7 @@ use self::{ pattern::QueryMapVc, }; use crate::{ - asset::{AssetVc, AssetsVc}, + asset::{AssetOptionVc, AssetVc, AssetsVc}, issue::{ package_json::{PackageJsonIssue, PackageJsonIssueVc}, resolve::{ResolvingIssue, ResolvingIssueVc}, @@ -59,176 +56,158 @@ pub use alias_map::{ }; pub use exports::{ExportsValue, ResolveAliasMap, ResolveAliasMapVc}; -#[derive(PartialEq, Eq, Clone, Debug, TraceRawVcs, Serialize, Deserialize)] -pub enum SpecialType { +#[turbo_tasks::value(shared)] +#[derive(Clone, Debug)] +pub enum PrimaryResolveResult { + Asset(AssetVc), OriginalReferenceExternal, OriginalReferenceTypeExternal(String), Ignore, Empty, Custom(u8), + Unresolveable, } #[turbo_tasks::value(shared)] #[derive(Clone, Debug)] -pub enum ResolveResult { - Single(AssetVc, Vec), - Keyed(HashMap, Vec), - Alternatives(Vec, Vec), - Special(SpecialType, Vec), - Unresolveable(Vec), +pub struct ResolveResult { + pub primary: Vec, + pub references: Vec, } impl Default for ResolveResult { fn default() -> Self { - ResolveResult::Unresolveable(Vec::new()) + ResolveResult::unresolveable() } } impl ResolveResult { pub fn unresolveable() -> Self { - ResolveResult::Unresolveable(Vec::new()) + ResolveResult { + primary: Vec::new(), + references: Vec::new(), + } } - pub fn add_reference(&mut self, reference: AssetReferenceVc) { - match self { - ResolveResult::Single(_, list) - | ResolveResult::Keyed(_, list) - | ResolveResult::Alternatives(_, list) - | ResolveResult::Special(_, list) - | ResolveResult::Unresolveable(list) => list.push(reference), + pub fn unresolveable_with_references(references: Vec) -> ResolveResult { + ResolveResult { + primary: Vec::new(), + references, } } - pub fn get_references(&self) -> &Vec { - match self { - ResolveResult::Single(_, list) - | ResolveResult::Keyed(_, list) - | ResolveResult::Alternatives(_, list) - | ResolveResult::Special(_, list) - | ResolveResult::Unresolveable(list) => list, + pub fn primary(result: PrimaryResolveResult) -> ResolveResult { + ResolveResult { + primary: vec![result], + references: Vec::new(), } } - fn clone_with_references(&self, references: Vec) -> ResolveResult { - match self { - ResolveResult::Single(asset, _) => ResolveResult::Single(*asset, references), - ResolveResult::Keyed(map, _) => ResolveResult::Keyed(map.clone(), references), - ResolveResult::Alternatives(alternatives, _) => { - ResolveResult::Alternatives(alternatives.clone(), references) - } - ResolveResult::Special(special_type, _) => { - ResolveResult::Special(special_type.clone(), references) - } - ResolveResult::Unresolveable(_) => ResolveResult::Unresolveable(references), + pub fn primary_with_references( + result: PrimaryResolveResult, + references: Vec, + ) -> ResolveResult { + ResolveResult { + primary: vec![result], + references, } } - pub fn merge_alternatives(&mut self, other: &ResolveResult) { - match self { - ResolveResult::Single(asset, list) => { - *self = ResolveResult::Alternatives(vec![*asset], take(list)) - } - ResolveResult::Keyed(_, list) => { - *self = ResolveResult::Unresolveable(take(list)); - } - ResolveResult::Alternatives(_, _) - | ResolveResult::Special(_, _) - | ResolveResult::Unresolveable(_) => { - // already is appropriate type - } + pub fn asset(asset: AssetVc) -> ResolveResult { + ResolveResult { + primary: vec![PrimaryResolveResult::Asset(asset)], + references: Vec::new(), } - match self { - ResolveResult::Single(_, _) | ResolveResult::Keyed(_, _) => { - unreachable!() - } - ResolveResult::Alternatives(assets, list) => match other { - ResolveResult::Single(asset, list2) => { - assets.push(*asset); - list.extend(list2.iter().cloned()); - } - ResolveResult::Alternatives(assets2, list2) => { - assets.extend(assets2.iter().cloned()); - list.extend(list2.iter().cloned()); - } - ResolveResult::Keyed(_, _) - | ResolveResult::Special(_, _) - | ResolveResult::Unresolveable(_) => { - list.extend(other.get_references().iter().cloned()); - } - }, - ResolveResult::Special(special, list) => match other { - ResolveResult::Special(special2, list2) if special2 == special => { - list.extend(list2.iter().cloned()); - } - ResolveResult::Unresolveable(list2) => { - list.extend(list2.iter().cloned()); - } - _ => { - list.extend(other.get_references().iter().cloned()); - *self = ResolveResult::Unresolveable(take(list)); - } - }, - ResolveResult::Unresolveable(list) => match other { - ResolveResult::Single(asset, list2) => { - list.extend(list2.iter().cloned()); - *self = ResolveResult::Alternatives(vec![*asset], take(list)); - } - ResolveResult::Alternatives(assets, list2) => { - list.extend(list2.iter().cloned()); - *self = ResolveResult::Alternatives(assets.clone(), take(list)); - } - ResolveResult::Special(special, list2) => { - list.extend(list2.iter().cloned()); - *self = ResolveResult::Special(special.clone(), take(list)); - } - ResolveResult::Keyed(_, _) | ResolveResult::Unresolveable(_) => { - list.extend(other.get_references().iter().cloned()); - } - }, + } + + pub fn asset_with_references( + asset: AssetVc, + references: Vec, + ) -> ResolveResult { + ResolveResult { + primary: vec![PrimaryResolveResult::Asset(asset)], + references, + } + } + + pub fn assets(assets: Vec) -> ResolveResult { + ResolveResult { + primary: assets + .into_iter() + .map(PrimaryResolveResult::Asset) + .collect(), + references: Vec::new(), + } + } + + pub fn assets_with_references( + assets: Vec, + references: Vec, + ) -> ResolveResult { + ResolveResult { + primary: assets + .into_iter() + .map(PrimaryResolveResult::Asset) + .collect(), + references, + } + } + + pub fn add_reference(&mut self, reference: AssetReferenceVc) { + self.references.push(reference); + } + + pub fn get_references(&self) -> &Vec { + &self.references + } + + fn clone_with_references(&self, references: Vec) -> ResolveResult { + ResolveResult { + primary: self.primary.clone(), + references, } } + pub fn merge_alternatives(&mut self, other: &ResolveResult) { + self.primary.extend(other.primary.iter().cloned()); + self.references.extend(other.references.iter().copied()); + } + pub fn is_unresolveable(&self) -> bool { - matches!(self, ResolveResult::Unresolveable(_)) + self.primary.is_empty() } - pub async fn map(&self, mut asset_fn: A, mut reference_fn: R) -> Result + pub async fn map(&self, asset_fn: A, reference_fn: R) -> Result where - A: FnMut(AssetVc) -> AF, + A: Fn(AssetVc) -> AF, AF: Future>, - R: FnMut(AssetReferenceVc) -> RF, + R: Fn(AssetReferenceVc) -> RF, RF: Future>, { - Ok(match self { - ResolveResult::Single(asset, refs) => { - let asset = asset_fn(*asset).await?; - let refs = refs.iter().map(|r| reference_fn(*r)).try_join().await?; - ResolveResult::Single(asset, refs) - } - ResolveResult::Keyed(map, refs) => { - let mut new_map = HashMap::new(); - for (key, value) in map.iter() { - new_map.insert(key.clone(), asset_fn(*value).await?); - } - let refs = refs.iter().map(|r| reference_fn(*r)).try_join().await?; - ResolveResult::Keyed(new_map, refs) - } - ResolveResult::Alternatives(assets, refs) => { - let mut new_assets = Vec::new(); - for asset in assets.iter() { - new_assets.push(asset_fn(*asset).await?); - } - let refs = refs.iter().map(|r| reference_fn(*r)).try_join().await?; - ResolveResult::Alternatives(new_assets, refs) - } - ResolveResult::Special(ty, refs) => { - let refs = refs.iter().map(|r| reference_fn(*r)).try_join().await?; - ResolveResult::Special(ty.clone(), refs) - } - ResolveResult::Unresolveable(refs) => { - let refs = refs.iter().map(|r| reference_fn(*r)).try_join().await?; - ResolveResult::Unresolveable(refs) - } + Ok(Self { + primary: self + .primary + .iter() + .cloned() + .map(|result| { + let asset_fn = &asset_fn; + async move { + if let PrimaryResolveResult::Asset(asset) = result { + Ok(PrimaryResolveResult::Asset(asset_fn(asset).await?)) + } else { + Ok(result) + } + } + }) + .try_join() + .await?, + references: self + .references + .iter() + .copied() + .map(reference_fn) + .try_join() + .await?, }) } } @@ -266,7 +245,7 @@ impl ResolveResultVc { return Ok(result_ref.clone_with_references(references).cell()); } } - Ok(ResolveResult::Unresolveable(references).into()) + Ok(ResolveResult::unresolveable_with_references(references).into()) } #[turbo_tasks::function] @@ -274,17 +253,17 @@ impl ResolveResultVc { if results.len() == 1 { return Ok(results.into_iter().next().unwrap()); } - let mut iter = results.into_iter(); + let mut iter = results.into_iter().try_join().await?.into_iter(); if let Some(current) = iter.next() { - let mut current = current.await?.clone_value(); + let mut current = current.clone_value(); for result in iter { // For clippy -- This explicit deref is necessary - let other = &*result.await?; + let other = &*result; current.merge_alternatives(other); } Ok(Self::cell(current)) } else { - Ok(Self::cell(ResolveResult::Unresolveable(Vec::new()))) + Ok(Self::cell(ResolveResult::unresolveable())) } } @@ -303,20 +282,20 @@ impl ResolveResultVc { .unwrap() .add_references(references)); } - let mut iter = results.into_iter(); + let mut iter = results.into_iter().try_join().await?.into_iter(); if let Some(current) = iter.next() { - let mut current = current.await?.clone_value(); - for reference in references { - current.add_reference(reference) - } - for result_vc in iter { + let mut current = current.clone_value(); + for result in iter { // For clippy -- This explicit deref is necessary - let result = &*result_vc.await?; - current.merge_alternatives(result); + let other = &*result; + current.merge_alternatives(other); } + current.references.extend(references); Ok(Self::cell(current)) } else { - Ok(Self::cell(ResolveResult::Unresolveable(references))) + Ok(Self::cell(ResolveResult::unresolveable_with_references( + references, + ))) } } @@ -326,15 +305,33 @@ impl ResolveResultVc { Ok(BoolVc::cell(this.is_unresolveable())) } + #[turbo_tasks::function] + pub async fn first_asset(self) -> Result { + let this = self.await?; + Ok(AssetOptionVc::cell(this.primary.iter().find_map(|item| { + if let PrimaryResolveResult::Asset(a) = item { + Some(*a) + } else { + None + } + }))) + } + #[turbo_tasks::function] pub async fn primary_assets(self) -> Result { let this = self.await?; - Ok(AssetsVc::cell(match &*this { - ResolveResult::Single(asset, _) => vec![*asset], - ResolveResult::Keyed(map, _) => map.values().copied().collect(), - ResolveResult::Alternatives(assets, _) => assets.clone(), - ResolveResult::Special(_, _) | ResolveResult::Unresolveable(_) => Vec::new(), - })) + Ok(AssetsVc::cell( + this.primary + .iter() + .filter_map(|item| { + if let PrimaryResolveResult::Asset(a) = item { + Some(*a) + } else { + None + } + }) + .collect(), + )) } } @@ -537,7 +534,7 @@ fn merge_results_with_references( return merge_results(results); } match results.len() { - 0 => ResolveResult::Unresolveable(references).into(), + 0 => ResolveResult::unresolveable_with_references(references).into(), 1 => results .into_iter() .next() @@ -555,7 +552,7 @@ pub async fn resolve_raw( ) -> Result { async fn to_result(path: FileSystemPathVc) -> Result { let RealPathResult { path, symlinks } = &*path.realpath_with_links().await?; - Ok(ResolveResult::Single( + Ok(ResolveResult::asset_with_references( SourceAssetVc::new(*path).into(), symlinks .iter() @@ -747,10 +744,9 @@ pub async fn resolve( Request::Uri { protocol, remainder, - } => ResolveResult::Special( - SpecialType::OriginalReferenceTypeExternal(format!("{}{}", protocol, remainder)), - Vec::new(), - ) + } => ResolveResult::primary(PrimaryResolveResult::OriginalReferenceTypeExternal( + format!("{}{}", protocol, remainder), + )) .into(), Request::Unknown { path } => { let issue: ResolvingIssueVc = ResolvingIssue { @@ -862,7 +858,7 @@ async fn resolve_module_request( .await?; if result.packages.is_empty() { - return Ok(ResolveResult::Unresolveable(result.references.clone()).into()); + return Ok(ResolveResult::unresolveable_with_references(result.references.clone()).into()); } let mut results = vec![]; @@ -1014,7 +1010,9 @@ async fn resolve_alias_field_result( field_name: &str, ) -> Result { if result.as_bool() == Some(false) { - return Ok(ResolveResult::Special(SpecialType::Ignore, refs).cell()); + return Ok( + ResolveResult::primary_with_references(PrimaryResolveResult::Ignore, refs).cell(), + ); } if let Some(value) = result.as_str() { return Ok(resolve( @@ -1033,7 +1031,7 @@ async fn resolve_alias_field_result( } .cell(); issue.as_issue().emit(); - Ok(ResolveResult::Unresolveable(refs).cell()) + Ok(ResolveResult::unresolveable_with_references(refs).cell()) } async fn resolved( @@ -1103,7 +1101,7 @@ async fn resolved( } } - Ok(ResolveResult::Single( + Ok(ResolveResult::asset_with_references( SourceAssetVc::new(*path).into(), symlinks .iter() @@ -1173,7 +1171,7 @@ impl AffectingResolvingAssetReferenceVc { impl AssetReference for AffectingResolvingAssetReference { #[turbo_tasks::function] fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::Single(SourceAssetVc::new(self.path).into(), Vec::new()).into() + ResolveResult::asset(SourceAssetVc::new(self.path).into()).into() } } diff --git a/crates/turbopack-core/src/resolve/options.rs b/crates/turbopack-core/src/resolve/options.rs index b8e973c1b17ec..efe77b8c63d99 100644 --- a/crates/turbopack-core/src/resolve/options.rs +++ b/crates/turbopack-core/src/resolve/options.rs @@ -10,7 +10,7 @@ use turbo_tasks_fs::{glob::GlobVc, FileSystemPathVc}; use super::{ alias_map::{AliasMap, AliasTemplate}, - AliasPattern, ResolveResult, ResolveResultVc, SpecialType, + AliasPattern, PrimaryResolveResult, ResolveResult, ResolveResultVc, }; use crate::resolve::{parse::RequestVc, plugin::ResolvePluginVc}; @@ -241,20 +241,20 @@ async fn import_mapping_to_result( Ok(match &*mapping.await? { ImportMapping::Direct(result) => ImportMapResult::Result(*result), ImportMapping::External(name) => ImportMapResult::Result( - ResolveResult::Special( + ResolveResult::primary_with_references( name.as_ref().map_or_else( - || SpecialType::OriginalReferenceExternal, - |req| SpecialType::OriginalReferenceTypeExternal(req.to_string()), + || PrimaryResolveResult::OriginalReferenceExternal, + |req| PrimaryResolveResult::OriginalReferenceTypeExternal(req.to_string()), ), Vec::new(), ) .into(), ), ImportMapping::Ignore => { - ImportMapResult::Result(ResolveResult::Special(SpecialType::Ignore, Vec::new()).into()) + ImportMapResult::Result(ResolveResult::primary(PrimaryResolveResult::Ignore).into()) } ImportMapping::Empty => { - ImportMapResult::Result(ResolveResult::Special(SpecialType::Empty, Vec::new()).into()) + ImportMapResult::Result(ResolveResult::primary(PrimaryResolveResult::Empty).into()) } ImportMapping::PrimaryAlternative(name, context) => { let request = RequestVc::parse(Value::new(name.to_string().into())); diff --git a/crates/turbopack-core/src/resolve/origin.rs b/crates/turbopack-core/src/resolve/origin.rs index ea9bc996c7bb8..f6ab28e10cb10 100644 --- a/crates/turbopack-core/src/resolve/origin.rs +++ b/crates/turbopack-core/src/resolve/origin.rs @@ -46,7 +46,7 @@ impl ResolveOriginVc { reference_type: Value, ) -> Result { if let Some(asset) = *self.get_inner_asset(request).await? { - return Ok(ResolveResult::Single(asset, Vec::new()).cell()); + return Ok(ResolveResult::asset(asset).cell()); } Ok(self .context() diff --git a/crates/turbopack-css/src/asset.rs b/crates/turbopack-css/src/asset.rs index ad02d3b3b26dc..5fd32f10ba9d3 100644 --- a/crates/turbopack-css/src/asset.rs +++ b/crates/turbopack-css/src/asset.rs @@ -14,7 +14,10 @@ use turbopack_core::{ chunk::{ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, ChunkableAssetVc, ChunkingContextVc}, context::AssetContextVc, reference::{AssetReference, AssetReferencesVc}, - resolve::origin::{ResolveOrigin, ResolveOriginVc}, + resolve::{ + origin::{ResolveOrigin, ResolveOriginVc}, + PrimaryResolveResult, + }, }; use crate::{ @@ -168,12 +171,14 @@ impl CssChunkItem for ModuleChunkItem { for reference in references.iter() { if let Some(import) = ImportAssetReferenceVc::resolve_from(reference).await? { - for asset in &*import.resolve_reference().primary_assets().await? { - if let Some(placeable) = CssChunkPlaceableVc::resolve_from(asset).await? { - imports.push(CssImport::Internal( - import, - placeable.as_chunk_item(context), - )); + for result in import.resolve_reference().await?.primary.iter() { + if let PrimaryResolveResult::Asset(asset) = result { + if let Some(placeable) = CssChunkPlaceableVc::resolve_from(asset).await? { + imports.push(CssImport::Internal( + import, + placeable.as_chunk_item(context), + )); + } } } } diff --git a/crates/turbopack-css/src/chunk/mod.rs b/crates/turbopack-css/src/chunk/mod.rs index 9f16ac67f85d2..b66dc46dbff81 100644 --- a/crates/turbopack-css/src/chunk/mod.rs +++ b/crates/turbopack-css/src/chunk/mod.rs @@ -18,6 +18,7 @@ use turbopack_core::{ }, code_builder::{CodeBuilder, CodeVc}, reference::{AssetReference, AssetReferenceVc, AssetReferencesVc}, + resolve::PrimaryResolveResult, source_map::{GenerateSourceMap, GenerateSourceMapVc, SourceMapVc}, }; use turbopack_ecmascript::utils::FormatIter; @@ -310,11 +311,12 @@ impl Asset for CssChunk { let mut references = Vec::new(); for r in content.external_asset_references.iter() { references.push(*r); - let assets = r.resolve_reference().primary_assets(); - for asset in assets.await?.iter() { - if let Some(embeddable) = CssEmbeddableVc::resolve_from(asset).await? { - let embed = embeddable.as_css_embed(this.context); - references.extend(embed.references().await?.iter()); + for result in r.resolve_reference().await?.primary.iter() { + if let PrimaryResolveResult::Asset(asset) = result { + if let Some(embeddable) = CssEmbeddableVc::resolve_from(asset).await? { + let embed = embeddable.as_css_embed(this.context); + references.extend(embed.references().await?.iter()); + } } } } diff --git a/crates/turbopack-css/src/chunk/source_map.rs b/crates/turbopack-css/src/chunk/source_map.rs index e98d5f784f803..4f173a3234f59 100644 --- a/crates/turbopack-css/src/chunk/source_map.rs +++ b/crates/turbopack-css/src/chunk/source_map.rs @@ -58,7 +58,7 @@ impl AssetReference for CssChunkSourceMapAssetReference { #[turbo_tasks::function] async fn resolve_reference(&self) -> Result { let source_maps = vec![CssChunkSourceMapAsset { chunk: self.chunk }.cell().into()]; - Ok(ResolveResult::Alternatives(source_maps, vec![]).cell()) + Ok(ResolveResult::assets_with_references(source_maps, vec![]).cell()) } } diff --git a/crates/turbopack-css/src/module_asset.rs b/crates/turbopack-css/src/module_asset.rs index 580987aff20a5..21f75d69b2cf5 100644 --- a/crates/turbopack-css/src/module_asset.rs +++ b/crates/turbopack-css/src/module_asset.rs @@ -154,7 +154,7 @@ impl ValueToString for CssProxyToCssAssetReference { impl AssetReference for CssProxyToCssAssetReference { #[turbo_tasks::function] fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::Single(self.module.into(), Vec::new()).cell() + ResolveResult::asset(self.module.into()).cell() } } diff --git a/crates/turbopack-css/src/references/url.rs b/crates/turbopack-css/src/references/url.rs index 0756a2646c197..6277f8c1447b6 100644 --- a/crates/turbopack-css/src/references/url.rs +++ b/crates/turbopack-css/src/references/url.rs @@ -12,7 +12,7 @@ use turbopack_core::{ resolve::{ origin::{ResolveOrigin, ResolveOriginVc}, parse::RequestVc, - ResolveResultVc, + PrimaryResolveResult, ResolveResultVc, }, }; use turbopack_ecmascript::resolve::url_resolve; @@ -51,13 +51,14 @@ impl UrlAssetReferenceVc { #[turbo_tasks::function] async fn get_referenced_asset(self, context: ChunkingContextVc) -> Result { - let assets = self.resolve_reference().primary_assets(); - for asset in assets.await?.iter() { - if let Some(embeddable) = CssEmbeddableVc::resolve_from(asset).await? { - return Ok(ReferencedAsset::Some( - embeddable.as_css_embed(context).embeddable_asset(), - ) - .into()); + for result in self.resolve_reference().await?.primary.iter() { + if let PrimaryResolveResult::Asset(asset) = result { + if let Some(embeddable) = CssEmbeddableVc::resolve_from(asset).await? { + return Ok(ReferencedAsset::Some( + embeddable.as_css_embed(context).embeddable_asset(), + ) + .into()); + } } } Ok(ReferencedAssetVc::cell(ReferencedAsset::None)) diff --git a/crates/turbopack-ecmascript/src/chunk/source_map.rs b/crates/turbopack-ecmascript/src/chunk/source_map.rs index 7f2f278009753..6d69f1733c3fb 100644 --- a/crates/turbopack-ecmascript/src/chunk/source_map.rs +++ b/crates/turbopack-ecmascript/src/chunk/source_map.rs @@ -67,7 +67,7 @@ impl AssetReference for EcmascriptChunkSourceMapAssetReference { let asset = EcmascriptChunkSourceMapAsset { chunk: self.chunk } .cell() .into(); - Ok(ResolveResult::Single(asset, vec![]).cell()) + Ok(ResolveResult::asset(asset).cell()) } } diff --git a/crates/turbopack-ecmascript/src/references/esm/base.rs b/crates/turbopack-ecmascript/src/references/esm/base.rs index c49ccefa1e58d..9d33f3a797af0 100644 --- a/crates/turbopack-ecmascript/src/references/esm/base.rs +++ b/crates/turbopack-ecmascript/src/references/esm/base.rs @@ -13,9 +13,7 @@ use turbopack_core::{ ChunkingTypeOptionVc, ModuleId, }, reference::{AssetReference, AssetReferenceVc}, - resolve::{ - origin::ResolveOriginVc, parse::RequestVc, ResolveResult, ResolveResultVc, SpecialType, - }, + resolve::{origin::ResolveOriginVc, parse::RequestVc, PrimaryResolveResult, ResolveResultVc}, }; use crate::{ @@ -63,23 +61,28 @@ impl ReferencedAssetVc { resolve_result: ResolveResultVc, request: RequestVc, ) -> Result { - match &*resolve_result.await? { - ResolveResult::Special(SpecialType::OriginalReferenceExternal, _) => { - if let Some(request) = request.await?.request() { - return Ok(ReferencedAsset::OriginalReferenceTypeExternal(request).cell()); - } else { - return Ok(ReferencedAssetVc::cell(ReferencedAsset::None)); + for result in resolve_result.await?.primary.iter() { + match result { + PrimaryResolveResult::OriginalReferenceExternal => { + if let Some(request) = request.await?.request() { + return Ok(ReferencedAsset::OriginalReferenceTypeExternal(request).cell()); + } else { + return Ok(ReferencedAssetVc::cell(ReferencedAsset::None)); + } } - } - ResolveResult::Special(SpecialType::OriginalReferenceTypeExternal(request), _) => { - return Ok(ReferencedAsset::OriginalReferenceTypeExternal(request.clone()).cell()); - } - _ => {} - } - let assets = resolve_result.primary_assets(); - for asset in assets.await?.iter() { - if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? { - return Ok(ReferencedAssetVc::cell(ReferencedAsset::Some(placeable))); + PrimaryResolveResult::OriginalReferenceTypeExternal(request) => { + return Ok( + ReferencedAsset::OriginalReferenceTypeExternal(request.clone()).cell(), + ); + } + PrimaryResolveResult::Asset(asset) => { + if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? + { + return Ok(ReferencedAssetVc::cell(ReferencedAsset::Some(placeable))); + } + } + // TODO ignore should probably be handled differently + _ => {} } } Ok(ReferencedAssetVc::cell(ReferencedAsset::None)) diff --git a/crates/turbopack-ecmascript/src/references/mod.rs b/crates/turbopack-ecmascript/src/references/mod.rs index 84c51466bb9be..d4f6683076858 100644 --- a/crates/turbopack-ecmascript/src/references/mod.rs +++ b/crates/turbopack-ecmascript/src/references/mod.rs @@ -39,7 +39,7 @@ use turbo_tasks_fs::FileSystemPathVc; use turbopack_core::{ asset::{Asset, AssetVc}, environment::EnvironmentVc, - reference::{AssetReferenceVc, AssetReferencesVc, SourceMapVc}, + reference::{AssetReferenceVc, AssetReferencesVc, SourceMapReferenceVc}, reference_type::{CommonJsReferenceSubType, ReferenceType}, resolve::{ find_context_file, @@ -47,7 +47,7 @@ use turbopack_core::{ package_json, parse::RequestVc, pattern::Pattern, - resolve, FindContextFileResult, ResolveResult, + resolve, FindContextFileResult, PrimaryResolveResult, }, }; use turbopack_swc_utils::emitter::IssueEmitter; @@ -274,7 +274,7 @@ pub(crate) async fn analyze_ecmascript_module( // TODO this probably needs to be a field in EcmascriptModuleAsset so it // knows to use that SourceMap when running code generation. // The reference is needed too for turbotrace - analysis.add_reference(SourceMapVc::new( + analysis.add_reference(SourceMapReferenceVc::new( source.path(), source.path().parent().join(path), )) @@ -1599,24 +1599,33 @@ async fn value_visitor_inner( let pat = js_value_to_pattern(&args[0]); let request = RequestVc::parse(Value::new(pat.clone())); let resolved = cjs_resolve(origin, request).await?; - match &*resolved { - ResolveResult::Single(asset, _) => require_resolve(asset.path()).await?, - ResolveResult::Alternatives(assets, _) => JsValue::alternatives( - assets - .iter() - .map(|asset| require_resolve(asset.path())) - .try_join() - .await?, - ), - _ => JsValue::Unknown( + let mut values = resolved + .primary + .iter() + .map(|result| async move { + Ok(if let PrimaryResolveResult::Asset(asset) = result { + Some(require_resolve(asset.path()).await?) + } else { + None + }) + }) + .try_join() + .await? + .into_iter() + .flatten() + .collect::>(); + match values.len() { + 0 => JsValue::Unknown( Some(Arc::new(JsValue::call( box JsValue::WellKnownFunction( WellKnownFunctionKind::RequireResolve, ), args, ))), - Box::leak(Box::new(format!("unresolveable request {pat}"))), + "unresolveable request", ), + 1 => values.pop().unwrap(), + _ => JsValue::alternatives(values), } } else { JsValue::Unknown( @@ -2114,8 +2123,8 @@ async fn resolve_as_webpack_runtime( options, ); - if let ResolveResult::Single(source, _) = &*resolved.await? { - Ok(webpack_runtime(*source, transforms)) + if let Some(source) = *resolved.first_asset().await? { + Ok(webpack_runtime(source, transforms)) } else { Ok(WebpackRuntime::None.into()) } diff --git a/crates/turbopack-ecmascript/src/references/node.rs b/crates/turbopack-ecmascript/src/references/node.rs index febd2ebb500cf..bb4d2278fb5cb 100644 --- a/crates/turbopack-ecmascript/src/references/node.rs +++ b/crates/turbopack-ecmascript/src/references/node.rs @@ -35,7 +35,7 @@ impl PackageJsonReferenceVc { impl AssetReference for PackageJsonReference { #[turbo_tasks::function] fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::Single(SourceAssetVc::new(self.package_json).into(), Vec::new()).into() + ResolveResult::asset(SourceAssetVc::new(self.package_json).into()).into() } } @@ -72,7 +72,7 @@ impl AssetReference for DirAssetReference { let context_path = self.source.path().await?; // ignore path.join in `node-gyp`, it will includes too many files if context_path.path.contains("node_modules/node-gyp") { - return Ok(ResolveResult::Alternatives(Vec::new(), vec![]).into()); + return Ok(ResolveResult::unresolveable().into()); } let context = self.source.path().parent(); let pat = self.path.await?; @@ -93,7 +93,7 @@ impl AssetReference for DirAssetReference { } _ => {} } - Ok(ResolveResult::Alternatives(result.into_iter().collect(), vec![]).into()) + Ok(ResolveResult::assets_with_references(result.into_iter().collect(), vec![]).into()) } } diff --git a/crates/turbopack-ecmascript/src/references/pattern_mapping.rs b/crates/turbopack-ecmascript/src/references/pattern_mapping.rs index 008ce756948d1..4679f6b398134 100644 --- a/crates/turbopack-ecmascript/src/references/pattern_mapping.rs +++ b/crates/turbopack-ecmascript/src/references/pattern_mapping.rs @@ -12,7 +12,7 @@ use turbopack_core::{ resolve::{ origin::{ResolveOrigin, ResolveOriginVc}, parse::RequestVc, - ResolveResult, ResolveResultVc, SpecialType, + PrimaryResolveResult, ResolveResultVc, }, }; @@ -119,30 +119,21 @@ impl PatternMappingVc { resolve_type: Value, ) -> Result { let result = resolve_result.await?; - let asset = match &*result { - ResolveResult::Alternatives(assets, _) => { - if let Some(asset) = assets.first() { - asset - } else { - return Ok(PatternMappingVc::cell(PatternMapping::Invalid)); - } + let asset = match result.primary.first() { + None => { + return Ok(PatternMapping::Unresolveable( + request_to_string(request).await?.to_string(), + ) + .cell()) } - ResolveResult::Single(asset, _) => asset, - ResolveResult::Special(SpecialType::OriginalReferenceExternal, _) => { + Some(PrimaryResolveResult::Asset(asset)) => *asset, + Some(PrimaryResolveResult::OriginalReferenceExternal) => { return Ok(PatternMapping::OriginalReferenceExternal.cell()) } - ResolveResult::Special(SpecialType::OriginalReferenceTypeExternal(s), _) => { + Some(PrimaryResolveResult::OriginalReferenceTypeExternal(s)) => { return Ok(PatternMapping::OriginalReferenceTypeExternal(s.clone()).cell()) } - ResolveResult::Special(SpecialType::Ignore, _) => { - return Ok(PatternMapping::Ignored.cell()) - } - ResolveResult::Unresolveable(_) => { - return Ok(PatternMapping::Unresolveable( - request_to_string(request).await?.to_string(), - ) - .cell()); - } + Some(PrimaryResolveResult::Ignore) => return Ok(PatternMapping::Ignored.cell()), _ => { // TODO implement mapping CodeGenerationIssue { @@ -174,7 +165,7 @@ impl PatternMappingVc { ))); } } else if let Some(chunk_item) = - EcmascriptChunkItemVc::from_asset(context, *asset).await? + EcmascriptChunkItemVc::from_asset(context, asset).await? { return Ok(PatternMappingVc::cell(PatternMapping::Single( chunk_item.id().await?.clone_value(), diff --git a/crates/turbopack-ecmascript/src/references/typescript.rs b/crates/turbopack-ecmascript/src/references/typescript.rs index da991725cdc06..159e90db5a32c 100644 --- a/crates/turbopack-ecmascript/src/references/typescript.rs +++ b/crates/turbopack-ecmascript/src/references/typescript.rs @@ -35,10 +35,9 @@ impl TsConfigReferenceVc { impl AssetReference for TsConfigReference { #[turbo_tasks::function] fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::Single( + ResolveResult::asset( TsConfigModuleAssetVc::new(self.origin, SourceAssetVc::new(self.tsconfig).into()) .into(), - Vec::new(), ) .into() } @@ -82,15 +81,12 @@ impl AssetReference for TsReferencePathAssetReference { .try_join(&self.path) .await? { - ResolveResult::Single( - self.origin.context().process( - SourceAssetVc::new(*path).into(), - Value::new(ReferenceType::TypeScript( - TypeScriptReferenceSubType::Undefined, - )), - ), - Vec::new(), - ) + ResolveResult::asset(self.origin.context().process( + SourceAssetVc::new(*path).into(), + Value::new(ReferenceType::TypeScript( + TypeScriptReferenceSubType::Undefined, + )), + )) .into() } else { ResolveResult::unresolveable().into() diff --git a/crates/turbopack-ecmascript/src/resolve/node_native_binding.rs b/crates/turbopack-ecmascript/src/resolve/node_native_binding.rs index 2400ed2a292ff..eea2648d82cdb 100644 --- a/crates/turbopack-ecmascript/src/resolve/node_native_binding.rs +++ b/crates/turbopack-ecmascript/src/resolve/node_native_binding.rs @@ -10,7 +10,8 @@ use turbopack_core::{ reference::{AssetReference, AssetReferenceVc}, resolve::{ pattern::{Pattern, PatternVc}, - resolve_raw, AffectingResolvingAssetReferenceVc, ResolveResult, ResolveResultVc, + resolve_raw, AffectingResolvingAssetReferenceVc, PrimaryResolveResult, ResolveResult, + ResolveResultVc, }, source_asset::SourceAssetVc, target::{CompileTargetVc, Platform}, @@ -92,12 +93,14 @@ pub async fn resolve_node_pre_gyp_files( static ref LIBC_TEMPLATE: Regex = Regex::new(r"\{libc\}").expect("create node_libc regex failed"); } - let config = resolve_raw(context, config_file_pattern, true).await?; + let config = resolve_raw(context, config_file_pattern, true) + .first_asset() + .await?; let compile_target = compile_target.await?; - if let ResolveResult::Single(ref config_path, _) = &*config { - if let AssetContent::File(file) = &*config_path.content().await? { + if let Some(config_asset) = *config { + if let AssetContent::File(file) = &*config_asset.content().await? { if let FileContent::Content(ref config_file) = &*file.await? { - let config_file_path = config_path.path(); + let config_file_path = config_asset.path(); let config_file_dir = config_file_path.parent(); let node_pre_gyp_config: NodePreGypConfigJson = serde_json::from_reader(config_file.read())?; @@ -145,7 +148,7 @@ pub async fn resolve_node_pre_gyp_files( } assets.insert(SourceAssetVc::new(resolved_file_vc).into()); } - for entry in config_path + for entry in config_asset .path() .parent() // TODO @@ -170,7 +173,7 @@ pub async fn resolve_node_pre_gyp_files( _ => {} } } - return Ok(ResolveResult::Alternatives( + return Ok(ResolveResult::assets_with_references( assets.into_iter().collect(), vec![AffectingResolvingAssetReferenceVc::new(config_file_path).into()], ) @@ -231,8 +234,8 @@ pub async fn resolve_node_gyp_build_files( } let binding_gyp_pat = PatternVc::new(Pattern::Constant("binding.gyp".to_owned())); let gyp_file = resolve_raw(context, binding_gyp_pat, true).await?; - if let ResolveResult::Single(binding_gyp, gyp_file_references) = &*gyp_file { - let mut merged_references = gyp_file_references.clone(); + if let [PrimaryResolveResult::Asset(binding_gyp)] = &gyp_file.primary[..] { + let mut merged_references = gyp_file.references.clone(); if let AssetContent::File(file) = &*binding_gyp.content().await? { if let FileContent::Content(config_file) = &*file.await? { if let Some(captured) = @@ -248,13 +251,15 @@ pub async fn resolve_node_gyp_build_files( true, ) .await?; - if let ResolveResult::Single(file, references) = &*resolved_prebuilt_file { - resolved.insert(SourceAssetVc::new(file.path()).into()); - merged_references.extend_from_slice(references); + if let [PrimaryResolveResult::Asset(asset)] = + &resolved_prebuilt_file.primary[..] + { + resolved.insert(asset.resolve().await?); + merged_references.extend_from_slice(&resolved_prebuilt_file.references); } } if !resolved.is_empty() { - return Ok(ResolveResult::Alternatives( + return Ok(ResolveResult::assets_with_references( resolved.into_iter().collect(), merged_references, ) @@ -330,14 +335,15 @@ pub async fn resolve_node_bindings_files( } let mut root_context = context; loop { - if let ResolveResult::Single(file, _) = &*resolve_raw( + let resolved = resolve_raw( root_context, Pattern::Constant("package.json".to_owned()).into(), true, ) - .await? - { - if let AssetContent::File(file) = &*file.content().await? { + .first_asset() + .await?; + if let Some(asset) = *resolved { + if let AssetContent::File(file) = &*asset.content().await? { if let FileContent::Content(_) = &*file.await? { break; } @@ -358,7 +364,7 @@ pub async fn resolve_node_bindings_files( }) .collect(); - Ok(ResolveResult::Alternatives( + Ok(ResolveResult::assets_with_references( bindings_try, vec![SourceAssetReferenceVc::new( SourceAssetVc::new(root_context).into(), diff --git a/crates/turbopack-ecmascript/src/typescript/mod.rs b/crates/turbopack-ecmascript/src/typescript/mod.rs index a24162688f5ec..45f50e8bb47e9 100644 --- a/crates/turbopack-ecmascript/src/typescript/mod.rs +++ b/crates/turbopack-ecmascript/src/typescript/mod.rs @@ -210,7 +210,7 @@ impl TsExtendsReferenceVc { impl AssetReference for TsExtendsReference { #[turbo_tasks::function] fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::Single(self.config, Vec::new()).into() + ResolveResult::asset(self.config).into() } } diff --git a/crates/turbopack-ecmascript/src/typescript/resolve.rs b/crates/turbopack-ecmascript/src/typescript/resolve.rs index fc2b7477e31da..4db217dc630c1 100644 --- a/crates/turbopack-ecmascript/src/typescript/resolve.rs +++ b/crates/turbopack-ecmascript/src/typescript/resolve.rs @@ -73,12 +73,12 @@ pub async fn read_tsconfigs( RequestVc::parse(Value::new(extends.to_string().into())), resolve_options, ) - .primary_assets() + .first_asset() .await?; // There might be multiple alternatives like // "some/path/node_modules/xyz/abc.json" and "some/node_modules/xyz/abc.json". // We only want to use the first one. - if let Some(&asset) = result.iter().next() { + if let Some(asset) = *result { data = asset.content().parse_json_with_comments(); tsconfig = asset; } else { diff --git a/crates/turbopack-ecmascript/src/webpack/mod.rs b/crates/turbopack-ecmascript/src/webpack/mod.rs index 8f3271ec82ed5..2dce8ebbf88da 100644 --- a/crates/turbopack-ecmascript/src/webpack/mod.rs +++ b/crates/turbopack-ecmascript/src/webpack/mod.rs @@ -92,9 +92,8 @@ impl AssetReference for WebpackChunkAssetReference { let filename = format!("./chunks/{}.js", chunk_id); let source = SourceAssetVc::new(context_path.join(&filename)).into(); - ResolveResult::Single( + ResolveResult::asset( WebpackModuleAssetVc::new(source, self.runtime, self.transforms).into(), - Vec::new(), ) .into() } @@ -127,9 +126,8 @@ pub struct WebpackEntryAssetReference { impl AssetReference for WebpackEntryAssetReference { #[turbo_tasks::function] fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::Single( + ResolveResult::asset( WebpackModuleAssetVc::new(self.source, self.runtime, self.transforms).into(), - Vec::new(), ) .into() } @@ -166,15 +164,16 @@ impl AssetReference for WebpackRuntimeAssetReference { options, ); - if let ResolveResult::Single(source, ref refs) = *resolved.await? { - return Ok(ResolveResult::Single( - WebpackModuleAssetVc::new(source, self.runtime, self.transforms).into(), - refs.clone(), + Ok(resolved + .await? + .map( + |source| async move { + Ok(WebpackModuleAssetVc::new(source, self.runtime, self.transforms).into()) + }, + |r| async move { Ok(r) }, ) - .into()); - } - - Ok(ResolveResult::unresolveable().into()) + .await? + .cell()) } } diff --git a/crates/turbopack-node/src/render/rendered_source.rs b/crates/turbopack-node/src/render/rendered_source.rs index e47e9c798e0ad..9bd3a18edd534 100644 --- a/crates/turbopack-node/src/render/rendered_source.rs +++ b/crates/turbopack-node/src/render/rendered_source.rs @@ -10,6 +10,7 @@ use turbopack_core::{ asset::IntrospectableAssetVc, Introspectable, IntrospectableChildrenVc, IntrospectableVc, }, reference::AssetReference, + resolve::PrimaryResolveResult, }; use turbopack_dev_server::{ html::DevHtmlAssetVc, @@ -105,10 +106,16 @@ impl GetContentSource for NodeRenderContentSource { set.extend( reference .resolve_reference() - .primary_assets() .await? + .primary .iter() - .copied(), + .filter_map(|result| { + if let PrimaryResolveResult::Asset(asset) = result { + Some(asset) + } else { + None + } + }), ) } for &entry in entries.await?.iter() {