diff --git a/Cargo.lock b/Cargo.lock index d8fdb388cba86..eae09d5475877 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9176,6 +9176,8 @@ dependencies = [ name = "turbopack-swc-utils" version = "0.1.0" dependencies = [ + "anyhow", + "parking_lot", "swc_core", "turbo-rcstr", "turbo-tasks", diff --git a/crates/next-api/src/project.rs b/crates/next-api/src/project.rs index edc1cebdfb737..884badb3897b1 100644 --- a/crates/next-api/src/project.rs +++ b/crates/next-api/src/project.rs @@ -785,7 +785,7 @@ impl Project { async fn collect_project_feature_telemetry(self: Vc) -> Result> { let emit_event = |feature_name: &str, enabled: bool| { NextFeatureTelemetry::new(feature_name.into(), enabled) - .cell() + .resolved_cell() .emit(); }; @@ -898,7 +898,7 @@ impl Project { .resolved_cell(), severity: IssueSeverity::Error.resolved_cell(), } - .cell() + .resolved_cell() .emit(); *entry.get_mut() = Route::Conflict; } diff --git a/crates/next-core/src/app_segment_config.rs b/crates/next-core/src/app_segment_config.rs index 9ba28dfd3ea0e..ec69bca75b21c 100644 --- a/crates/next-core/src/app_segment_config.rs +++ b/crates/next-core/src/app_segment_config.rs @@ -1,4 +1,4 @@ -use std::ops::Deref; +use std::{future::Future, ops::Deref}; use anyhow::{bail, Result}; use serde::{Deserialize, Serialize}; @@ -8,7 +8,9 @@ use swc_core::{ ecma::ast::{Decl, Expr, FnExpr, Ident, Program}, }; use turbo_rcstr::RcStr; -use turbo_tasks::{trace::TraceRawVcs, ResolvedVc, TryJoinIterExt, ValueDefault, Vc}; +use turbo_tasks::{ + trace::TraceRawVcs, util::WrapFuture, ResolvedVc, TryJoinIterExt, ValueDefault, Vc, +}; use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ file_source::FileSource, @@ -292,43 +294,49 @@ pub async fn parse_segment_config_from_source( return Ok(Default::default()); }; - let config = GLOBALS.set(globals, || { - let mut config = NextSegmentConfig::default(); - - for item in &module_ast.body { - let Some(export_decl) = item - .as_module_decl() - .and_then(|mod_decl| mod_decl.as_export_decl()) - else { - continue; - }; - - match &export_decl.decl { - Decl::Var(var_decl) => { - for decl in &var_decl.decls { - let Some(ident) = decl.name.as_ident().map(|ident| ident.deref()) else { - continue; - }; - - if let Some(init) = decl.init.as_ref() { - parse_config_value(source, &mut config, ident, init, eval_context); + let config = WrapFuture::new( + async { + let mut config = NextSegmentConfig::default(); + + for item in &module_ast.body { + let Some(export_decl) = item + .as_module_decl() + .and_then(|mod_decl| mod_decl.as_export_decl()) + else { + continue; + }; + + match &export_decl.decl { + Decl::Var(var_decl) => { + for decl in &var_decl.decls { + let Some(ident) = decl.name.as_ident().map(|ident| ident.deref()) + else { + continue; + }; + + if let Some(init) = decl.init.as_ref() { + parse_config_value(source, &mut config, ident, init, eval_context) + .await?; + } } } + Decl::Fn(fn_decl) => { + let ident = &fn_decl.ident; + // create an empty expression of {}, we don't need init for function + let init = Expr::Fn(FnExpr { + ident: None, + function: fn_decl.function.clone(), + }); + parse_config_value(source, &mut config, ident, &init, eval_context).await?; + } + _ => {} } - Decl::Fn(fn_decl) => { - let ident = &fn_decl.ident; - // create an empty expression of {}, we don't need init for function - let init = Expr::Fn(FnExpr { - ident: None, - function: fn_decl.function.clone(), - }); - parse_config_value(source, &mut config, ident, &init, eval_context); - } - _ => {} } - } - config - }); + anyhow::Ok(config) + }, + |f, ctx| GLOBALS.set(globals, || f.poll(ctx)), + ) + .await?; Ok(config.cell()) } @@ -337,44 +345,70 @@ fn issue_source(source: Vc>, span: Span) -> Vc { IssueSource::from_swc_offsets(source, span.lo.to_usize(), span.hi.to_usize()) } -fn parse_config_value( +async fn parse_config_value( source: Vc>, config: &mut NextSegmentConfig, ident: &Ident, init: &Expr, eval_context: &EvalContext, -) { +) -> Result<()> { let span = init.span(); - let invalid_config = |detail: &str, value: &JsValue| { + async fn invalid_config( + source: Vc>, + span: Span, + detail: &str, + value: &JsValue, + ) -> Result<()> { let (explainer, hints) = value.explain(2, 0); let detail = StyledString::Text(format!("{detail} Got {explainer}.{hints}").into()).resolved_cell(); NextSegmentConfigParsingIssue::new(source.ident(), *detail, issue_source(source, span)) + .to_resolved() + .await? .emit(); - }; + Ok(()) + } match &*ident.sym { "dynamic" => { let value = eval_context.eval(init); let Some(val) = value.as_str() else { - invalid_config("`dynamic` needs to be a static string", &value); - return; + invalid_config( + source, + span, + "`dynamic` needs to be a static string", + &value, + ) + .await?; + return Ok(()); }; config.dynamic = match serde_json::from_value(Value::String(val.to_string())) { Ok(dynamic) => Some(dynamic), Err(err) => { - invalid_config(&format!("`dynamic` has an invalid value: {}", err), &value); - return; + invalid_config( + source, + span, + &format!("`dynamic` has an invalid value: {}", err), + &value, + ) + .await?; + return Ok(()); } }; } "dynamicParams" => { let value = eval_context.eval(init); let Some(val) = value.as_bool() else { - invalid_config("`dynamicParams` needs to be a static boolean", &value); - return; + invalid_config( + source, + span, + "`dynamicParams` needs to be a static boolean", + &value, + ) + .await?; + return Ok(()); }; config.dynamic_params = Some(val); @@ -402,33 +436,50 @@ fn parse_config_value( "fetchCache" => { let value = eval_context.eval(init); let Some(val) = value.as_str() else { - invalid_config("`fetchCache` needs to be a static string", &value); - return; + return invalid_config( + source, + span, + "`fetchCache` needs to be a static string", + &value, + ) + .await; }; config.fetch_cache = match serde_json::from_value(Value::String(val.to_string())) { Ok(fetch_cache) => Some(fetch_cache), Err(err) => { - invalid_config( + return invalid_config( + source, + span, &format!("`fetchCache` has an invalid value: {}", err), &value, - ); - return; + ) + .await; } }; } "runtime" => { let value = eval_context.eval(init); let Some(val) = value.as_str() else { - invalid_config("`runtime` needs to be a static string", &value); - return; + return invalid_config( + source, + span, + "`runtime` needs to be a static string", + &value, + ) + .await; }; config.runtime = match serde_json::from_value(Value::String(val.to_string())) { Ok(runtime) => Some(runtime), Err(err) => { - invalid_config(&format!("`runtime` has an invalid value: {}", err), &value); - return; + return invalid_config( + source, + span, + &format!("`runtime` has an invalid value: {}", err), + &value, + ) + .await; } }; } @@ -446,21 +497,25 @@ fn parse_config_value( if let JsValue::Constant(ConstantValue::Str(str)) = item { regions.push(str.to_string().into()); } else { - invalid_config( + return invalid_config( + source, + span, "Values of the `preferredRegion` array need to static strings", &item, - ); - return; + ) + .await; } } regions } _ => { - invalid_config( + return invalid_config( + source, + span, "`preferredRegion` needs to be a static string or array of static strings", &value, - ); - return; + ) + .await; } }; @@ -477,14 +532,21 @@ fn parse_config_value( "experimental_ppr" => { let value = eval_context.eval(init); let Some(val) = value.as_bool() else { - invalid_config("`experimental_ppr` needs to be a static boolean", &value); - return; + return invalid_config( + source, + span, + "`experimental_ppr` needs to be a static boolean", + &value, + ) + .await; }; config.experimental_ppr = Some(val); } _ => {} } + + Ok(()) } #[turbo_tasks::function] diff --git a/crates/next-core/src/app_structure.rs b/crates/next-core/src/app_structure.rs index e18b74ca9b675..e39c21f6aa5e6 100644 --- a/crates/next-core/src/app_structure.rs +++ b/crates/next-core/src/app_structure.rs @@ -565,7 +565,7 @@ fn conflict_issue( .resolved_cell(), severity: IssueSeverity::Error.resolved_cell(), } - .cell() + .resolved_cell() .emit(); } @@ -803,7 +803,7 @@ async fn check_duplicate( app_dir: app_dir.to_resolved().await?, page: loader_tree.page.clone(), } - .cell() + .resolved_cell() .emit(); } } diff --git a/crates/next-core/src/next_font/google/font_fallback.rs b/crates/next-core/src/next_font/google/font_fallback.rs index d2f9351f932c6..3e88a5f73d96f 100644 --- a/crates/next-core/src/next_font/google/font_fallback.rs +++ b/crates/next-core/src/next_font/google/font_fallback.rs @@ -92,7 +92,7 @@ pub(super) async fn get_font_fallback( .resolved_cell(), severity: IssueSeverity::Warning.resolved_cell(), } - .cell() + .resolved_cell() .emit(); FontFallback::Error.cell() } diff --git a/crates/next-core/src/next_font/google/mod.rs b/crates/next-core/src/next_font/google/mod.rs index 4e16217835e59..044dec70cca75 100644 --- a/crates/next-core/src/next_font/google/mod.rs +++ b/crates/next-core/src/next_font/google/mod.rs @@ -637,6 +637,8 @@ async fn fetch_from_google_fonts( // TODO(WEB-283): Use fallback in dev in this case // TODO(WEB-293): Fail production builds (not dev) in this case err.to_issue(IssueSeverity::Warning.into(), virtual_path) + .to_resolved() + .await? .emit(); None diff --git a/crates/next-core/src/next_font/local/mod.rs b/crates/next-core/src/next_font/local/mod.rs index 3221134f348dc..988c8df834f4b 100644 --- a/crates/next-core/src/next_font/local/mod.rs +++ b/crates/next-core/src/next_font/local/mod.rs @@ -119,7 +119,7 @@ impl BeforeResolvePlugin for NextFontLocalResolvePlugin { origin_path: lookup_path, font_path: ResolvedVc::cell(font_path.clone()), } - .cell() + .resolved_cell() .emit(); return Ok(ResolveResultOption::some( diff --git a/crates/next-core/src/next_server/resolve.rs b/crates/next-core/src/next_server/resolve.rs index 015b286ffedc5..3a48b8de42fd2 100644 --- a/crates/next-core/src/next_server/resolve.rs +++ b/crates/next-core/src/next_server/resolve.rs @@ -205,7 +205,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { request_str: request_str.clone(), reason, } - .cell() + .resolved_cell() .emit(); } Ok(ResolveResultOption::none()) diff --git a/crates/next-core/src/next_shared/resolve.rs b/crates/next-core/src/next_shared/resolve.rs index f4c80d0aadef9..43449081d84a9 100644 --- a/crates/next-core/src/next_shared/resolve.rs +++ b/crates/next-core/src/next_shared/resolve.rs @@ -142,7 +142,7 @@ impl BeforeResolvePlugin for InvalidImportResolvePlugin { // styled-jsx specific resolve error has its own message skip_context_message: self.invalid_import == "styled-jsx", } - .cell() + .resolved_cell() .emit(); ResolveResultOption::some( @@ -383,7 +383,7 @@ impl BeforeResolvePlugin for ModuleFeatureReportResolvePlugin { if let Some(sub_path) = sub_path { ModuleFeatureTelemetry::new(format!("{}{}", module, sub_path).into(), 1) - .cell() + .resolved_cell() .emit(); } } diff --git a/crates/next-core/src/next_shared/transforms/next_page_static_info.rs b/crates/next-core/src/next_shared/transforms/next_page_static_info.rs index fd24503769cab..d57864d4d73e0 100644 --- a/crates/next-core/src/next_shared/transforms/next_page_static_info.rs +++ b/crates/next-core/src/next_shared/transforms/next_page_static_info.rs @@ -76,7 +76,7 @@ impl CustomTransformer for NextPageStaticInfo { ], severity: IssueSeverity::Warning, } - .cell() + .resolved_cell() .emit(); } } @@ -105,7 +105,7 @@ impl CustomTransformer for NextPageStaticInfo { messages, severity: IssueSeverity::Warning, } - .cell() + .resolved_cell() .emit(); } } @@ -119,7 +119,7 @@ impl CustomTransformer for NextPageStaticInfo { messages: vec![format!(r#"Page "{}" cannot use both "use client" and export function "generateStaticParams()"."#, ctx.file_path_str)], severity: IssueSeverity::Error, } - .cell() + .resolved_cell() .emit(); } } diff --git a/crates/next-core/src/next_shared/webpack_rules/babel.rs b/crates/next-core/src/next_shared/webpack_rules/babel.rs index 6c9cfddea62a4..5b63d2a8345b8 100644 --- a/crates/next-core/src/next_shared/webpack_rules/babel.rs +++ b/crates/next-core/src/next_shared/webpack_rules/babel.rs @@ -76,7 +76,7 @@ pub async fn maybe_add_babel_loader( .resolved_cell(), severity: IssueSeverity::Fatal.resolved_cell(), } - .cell() + .resolved_cell() .emit(); has_emitted_babel_resolve_issue = true; diff --git a/crates/next-core/src/util.rs b/crates/next-core/src/util.rs index f2ea8baa64c7c..0040b7c0ec77b 100644 --- a/crates/next-core/src/util.rs +++ b/crates/next-core/src/util.rs @@ -1,3 +1,5 @@ +use std::future::Future; + use anyhow::{bail, Context, Result}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use swc_core::{ @@ -6,8 +8,8 @@ use swc_core::{ }; use turbo_rcstr::RcStr; use turbo_tasks::{ - trace::TraceRawVcs, FxIndexMap, FxIndexSet, ResolvedVc, TaskInput, ValueDefault, ValueToString, - Vc, + trace::TraceRawVcs, util::WrapFuture, FxIndexMap, FxIndexSet, ResolvedVc, TaskInput, + ValueDefault, ValueToString, Vc, }; use turbo_tasks_fs::{ self, json::parse_json_rope_with_source_context, rope::Rope, util::join_path, File, @@ -248,19 +250,26 @@ impl Issue for NextSourceConfigParsingIssue { } } -fn emit_invalid_config_warning(ident: Vc, detail: &str, value: &JsValue) { +async fn emit_invalid_config_warning( + ident: Vc, + detail: &str, + value: &JsValue, +) -> Result<()> { let (explainer, hints) = value.explain(2, 0); NextSourceConfigParsingIssue::new( ident, StyledString::Text(format!("{detail} Got {explainer}.{hints}").into()).cell(), ) + .to_resolved() + .await? .emit(); + Ok(()) } -fn parse_route_matcher_from_js_value( +async fn parse_route_matcher_from_js_value( ident: Vc, value: &JsValue, -) -> Option> { +) -> Result>> { let parse_matcher_kind_matcher = |value: &JsValue| { let mut route_has = vec![]; if let JsValue::Array { items, .. } = value { @@ -326,7 +335,8 @@ fn parse_route_matcher_from_js_value( ident, "The matcher property must be a string or array of strings", value, - ); + ) + .await?; } } JsValue::Array { items, .. } => { @@ -362,22 +372,26 @@ fn parse_route_matcher_from_js_value( ident, "The matcher property must be a string or array of strings", value, - ); + ) + .await?; } } } - _ => emit_invalid_config_warning( - ident, - "The matcher property must be a string or array of strings", - value, - ), + _ => { + emit_invalid_config_warning( + ident, + "The matcher property must be a string or array of strings", + value, + ) + .await? + } } - if matchers.is_empty() { + Ok(if matchers.is_empty() { None } else { Some(matchers) - } + }) } #[turbo_tasks::function] @@ -410,10 +424,16 @@ pub async fn parse_config_from_source( .unwrap_or_default() { if let Some(init) = decl.init.as_ref() { - return GLOBALS.set(globals, || { - let value = eval_context.eval(init); - Ok(parse_config_from_js_value(*module, &value).cell()) - }); + return WrapFuture::new( + async { + let value = eval_context.eval(init); + Ok(parse_config_from_js_value(*module, &value) + .await? + .cell()) + }, + |f, ctx| GLOBALS.set(globals, || f.poll(ctx)), + ) + .await; } else { NextSourceConfigParsingIssue::new( module.ident(), @@ -424,6 +444,8 @@ pub async fn parse_config_from_source( ) .cell(), ) + .to_resolved() + .await? .emit(); } } @@ -440,7 +462,9 @@ pub async fn parse_config_from_source( .into(), ) .cell(), - ); + ) + .to_resolved() + .await?; if let Some(init) = decl.init.as_ref() { // skipping eval and directly read the expr's value, as we know it // should be a const string @@ -474,6 +498,8 @@ pub async fn parse_config_from_source( ) .cell(), ) + .to_resolved() + .await? .emit(); } } @@ -485,17 +511,23 @@ pub async fn parse_config_from_source( Ok(Default::default()) } -fn parse_config_from_js_value(module: Vc>, value: &JsValue) -> NextSourceConfig { +async fn parse_config_from_js_value( + module: Vc>, + value: &JsValue, +) -> Result { let mut config = NextSourceConfig::default(); if let JsValue::Object { parts, .. } = value { for part in parts { match part { - ObjectPart::Spread(_) => emit_invalid_config_warning( - module.ident(), - "Spread properties are not supported in the config export.", - value, - ), + ObjectPart::Spread(_) => { + emit_invalid_config_warning( + module.ident(), + "Spread properties are not supported in the config export.", + value, + ) + .await? + } ObjectPart::KeyValue(key, value) => { if let Some(key) = key.as_str() { match key { @@ -515,7 +547,8 @@ fn parse_config_from_js_value(module: Vc>, value: &JsValue) -> N "The runtime property must be either \ \"nodejs\" or \"edge\".", value, - ); + ) + .await?; } } } @@ -524,12 +557,14 @@ fn parse_config_from_js_value(module: Vc>, value: &JsValue) -> N module.ident(), "The runtime property must be a constant string.", value, - ); + ) + .await?; } } "matcher" => { config.matcher = - parse_route_matcher_from_js_value(module.ident(), value); + parse_route_matcher_from_js_value(module.ident(), value) + .await?; } "regions" => { config.regions = match value { @@ -552,7 +587,8 @@ fn parse_config_from_js_value(module: Vc>, value: &JsValue) -> N "Values of the `config.regions` array need to \ static strings", item, - ); + ) + .await?; } } Some(regions) @@ -563,7 +599,8 @@ fn parse_config_from_js_value(module: Vc>, value: &JsValue) -> N "`config.regions` needs to be a static string or \ array of static strings", value, - ); + ) + .await?; None } }; @@ -575,7 +612,8 @@ fn parse_config_from_js_value(module: Vc>, value: &JsValue) -> N module.ident(), "The exported config object must not contain non-constant strings.", key, - ); + ) + .await?; } } } @@ -585,10 +623,11 @@ fn parse_config_from_js_value(module: Vc>, value: &JsValue) -> N module.ident(), "The exported config object must be a valid object literal.", value, - ); + ) + .await?; } - config + Ok(config) } /// Loads a next.js template, replaces `replacements` and `injections` and makes diff --git a/turbopack/crates/turbo-tasks-testing/tests/collectibles.rs b/turbopack/crates/turbo-tasks-testing/tests/collectibles.rs index 9cb297eabf2be..b8d04bdaf61ef 100644 --- a/turbopack/crates/turbo-tasks-testing/tests/collectibles.rs +++ b/turbopack/crates/turbo-tasks-testing/tests/collectibles.rs @@ -209,8 +209,10 @@ async fn my_transitive_emitting_function_with_child_scope( #[turbo_tasks::function] async fn my_emitting_function(_key: RcStr) -> Result<()> { sleep(Duration::from_millis(100)).await; - emit(Vc::upcast::>(Thing::new(123))); - emit(Vc::upcast::>(Thing::new(42))); + emit(ResolvedVc::upcast::>(Thing::new( + 123, + ))); + emit(ResolvedVc::upcast::>(Thing::new(42))); Ok(()) } @@ -218,8 +220,8 @@ async fn my_emitting_function(_key: RcStr) -> Result<()> { struct Thing(u32); impl Thing { - fn new(v: u32) -> Vc { - Self::cell(Thing(v)) + fn new(v: u32) -> ResolvedVc { + Self::resolved_cell(Thing(v)) } } diff --git a/turbopack/crates/turbo-tasks-testing/tests/dirty_in_progress.rs b/turbopack/crates/turbo-tasks-testing/tests/dirty_in_progress.rs index a4a9767a47816..6ea1877472aeb 100644 --- a/turbopack/crates/turbo-tasks-testing/tests/dirty_in_progress.rs +++ b/turbopack/crates/turbo-tasks-testing/tests/dirty_in_progress.rs @@ -6,7 +6,7 @@ use std::time::Duration; use anyhow::{bail, Result}; use turbo_rcstr::RcStr; -use turbo_tasks::{emit, CollectiblesSource, State, ValueToString, Vc}; +use turbo_tasks::{emit, CollectiblesSource, ResolvedVc, State, ValueToString, Vc}; use turbo_tasks_testing::{register, run, Registration}; static REGISTRATION: Registration = register!(); @@ -77,7 +77,8 @@ async fn inner_compute(input: Vc) -> Result> { let value = *input.await?.state.get(); tokio::time::sleep(Duration::from_millis(200)).await; if value > 10 { - let collectible: Vc> = Vc::upcast(Collectible { value }.cell()); + let collectible: ResolvedVc> = + ResolvedVc::upcast(Collectible { value }.resolved_cell()); emit(collectible); println!("end inner_compute with collectible"); diff --git a/turbopack/crates/turbo-tasks-testing/tests/recompute_collectibles.rs b/turbopack/crates/turbo-tasks-testing/tests/recompute_collectibles.rs index 64c2c975670da..7f05bdb856aee 100644 --- a/turbopack/crates/turbo-tasks-testing/tests/recompute_collectibles.rs +++ b/turbopack/crates/turbo-tasks-testing/tests/recompute_collectibles.rs @@ -4,7 +4,7 @@ use anyhow::{bail, Result}; use turbo_rcstr::RcStr; -use turbo_tasks::{emit, CollectiblesSource, State, ValueToString, Vc}; +use turbo_tasks::{emit, CollectiblesSource, ResolvedVc, State, ValueToString, Vc}; use turbo_tasks_testing::{register, run, Registration}; static REGISTRATION: Registration = register!(); @@ -67,11 +67,11 @@ async fn inner_compute2(input: Vc, innerness: u32) -> Result 0 { return Ok(inner_compute2(input, innerness - 1)); } - let collectible: Vc> = Vc::upcast( + let collectible: ResolvedVc> = ResolvedVc::upcast( Collectible { value: *input.await?.state.get(), } - .cell(), + .resolved_cell(), ); emit(collectible); diff --git a/turbopack/crates/turbo-tasks/src/effect.rs b/turbopack/crates/turbo-tasks/src/effect.rs index 13367aeebe9d7..b2b3179b5b3e0 100644 --- a/turbopack/crates/turbo-tasks/src/effect.rs +++ b/turbopack/crates/turbo-tasks/src/effect.rs @@ -11,7 +11,7 @@ use crate::{ event::{Event, EventListener}, manager::turbo_tasks_future_scope, util::SharedError, - CollectiblesSource, ReadRef, TryJoinIterExt, Vc, + CollectiblesSource, ReadRef, ResolvedVc, TryJoinIterExt, Vc, }; /// A trait to emit a task effect as collectible. This trait only has one @@ -138,7 +138,9 @@ impl Effect for EffectInstance {} /// Order of execution of multiple effects is not defined. You must not use mutliple conflicting /// effects to avoid non-deterministic behavior. pub fn effect(future: impl Future> + Send + Sync + 'static) { - emit::>(Vc::upcast(EffectInstance::new(future).cell())); + emit::>(ResolvedVc::upcast( + EffectInstance::new(future).resolved_cell(), + )); } /// Applies all effects that have been emitted by an operations. diff --git a/turbopack/crates/turbo-tasks/src/manager.rs b/turbopack/crates/turbo-tasks/src/manager.rs index 90a02fed2dd2d..c208548c678ce 100644 --- a/turbopack/crates/turbo-tasks/src/manager.rs +++ b/turbopack/crates/turbo-tasks/src/manager.rs @@ -45,8 +45,8 @@ use crate::{ trait_helpers::get_trait_method, util::StaticOrArc, vc::ReadVcFuture, - Completion, FunctionMeta, InvalidationReason, InvalidationReasonSet, SharedReference, TaskId, - TaskIdSet, ValueTypeId, Vc, VcRead, VcValueTrait, VcValueType, + Completion, FunctionMeta, InvalidationReason, InvalidationReasonSet, ResolvedVc, + SharedReference, TaskId, TaskIdSet, ValueTypeId, Vc, VcRead, VcValueTrait, VcValueType, }; pub trait TurboTasksCallApi: Sync + Send { @@ -1748,8 +1748,11 @@ pub fn notify_scheduled_tasks() { with_turbo_tasks(|tt| tt.notify_scheduled_tasks()) } -pub fn emit(collectible: Vc) { - with_turbo_tasks(|tt| tt.emit_collectible(T::get_trait_type_id(), collectible.node)) +pub fn emit(collectible: ResolvedVc) { + with_turbo_tasks(|tt| { + let raw_vc = collectible.node.node; + tt.emit_collectible(T::get_trait_type_id(), raw_vc) + }) } pub async fn spawn_blocking(func: impl FnOnce() -> T + Send + 'static) -> T { diff --git a/turbopack/crates/turbopack-browser/src/ecmascript/content_entry.rs b/turbopack/crates/turbopack-browser/src/ecmascript/content_entry.rs index e189af527fc28..c0aa848cd3b20 100644 --- a/turbopack/crates/turbopack-browser/src/ecmascript/content_entry.rs +++ b/turbopack/crates/turbopack-browser/src/ecmascript/content_entry.rs @@ -106,7 +106,7 @@ async fn item_code( .resolved_cell(), message: StyledString::Text(error_message.into()).resolved_cell(), } - .cell() + .resolved_cell() .emit(); let mut code = CodeBuilder::default(); code += "(() => {{\n\n"; diff --git a/turbopack/crates/turbopack-browser/src/react_refresh.rs b/turbopack/crates/turbopack-browser/src/react_refresh.rs index 0cd474bcf19dc..47595ed0007f6 100644 --- a/turbopack/crates/turbopack-browser/src/react_refresh.rs +++ b/turbopack/crates/turbopack-browser/src/react_refresh.rs @@ -65,7 +65,7 @@ pub async fn assert_can_resolve_react_refresh( return Ok(ResolveReactRefreshResult::Found(request.to_resolved().await?).cell()); } } - ReactRefreshResolvingIssue { path }.cell().emit(); + ReactRefreshResolvingIssue { path }.resolved_cell().emit(); Ok(ResolveReactRefreshResult::NotFound.cell()) } diff --git a/turbopack/crates/turbopack-core/src/diagnostics/mod.rs b/turbopack/crates/turbopack-core/src/diagnostics/mod.rs index 8d6efbe4c7658..2b3e89120062f 100644 --- a/turbopack/crates/turbopack-core/src/diagnostics/mod.rs +++ b/turbopack/crates/turbopack-core/src/diagnostics/mod.rs @@ -76,12 +76,12 @@ pub trait DiagnosticExt { fn emit(self); } -impl DiagnosticExt for Vc +impl DiagnosticExt for ResolvedVc where T: Upcast>, { fn emit(self) { - let diagnostic = Vc::upcast::>(self); + let diagnostic = ResolvedVc::upcast::>(self); emit(diagnostic); } } diff --git a/turbopack/crates/turbopack-core/src/issue/mod.rs b/turbopack/crates/turbopack-core/src/issue/mod.rs index 0a8a9380c3884..d3eadf1f4e4c7 100644 --- a/turbopack/crates/turbopack-core/src/issue/mod.rs +++ b/turbopack/crates/turbopack-core/src/issue/mod.rs @@ -265,12 +265,15 @@ impl OptionIssueProcessingPathItems { } #[turbo_tasks::value] -struct RootIssueProcessingPath(Vc>); +struct RootIssueProcessingPath(ResolvedVc>); #[turbo_tasks::value_impl] impl IssueProcessingPath for RootIssueProcessingPath { #[turbo_tasks::function] - fn shortest_path(&self, issue: Vc>) -> Vc { + fn shortest_path( + &self, + issue: ResolvedVc>, + ) -> Vc { if self.0 == issue { Vc::cell(Some(Vec::new())) } else { @@ -341,15 +344,15 @@ pub trait IssueExt { fn emit(self); } -impl IssueExt for Vc +impl IssueExt for ResolvedVc where T: Upcast>, { fn emit(self) { - let issue = Vc::upcast::>(self); + let issue = ResolvedVc::upcast::>(self); emit(issue); - emit(Vc::upcast::>( - RootIssueProcessingPath::cell(RootIssueProcessingPath(issue)), + emit(ResolvedVc::upcast::>( + RootIssueProcessingPath::resolved_cell(RootIssueProcessingPath(issue)), )) } } @@ -911,8 +914,8 @@ where { let children = self.take_collectibles(); if !children.is_empty() { - emit(Vc::upcast::>( - ItemIssueProcessingPath::cell(ItemIssueProcessingPath( + emit(ResolvedVc::upcast::>( + ItemIssueProcessingPath::resolved_cell(ItemIssueProcessingPath( Some(IssueProcessingPathItem::resolved_cell( IssueProcessingPathItem { file_path: match file_path.into() { @@ -950,8 +953,8 @@ where { let children = self.take_collectibles(); if !children.is_empty() { - emit(Vc::upcast::>( - ItemIssueProcessingPath::cell(ItemIssueProcessingPath( + emit(ResolvedVc::upcast::>( + ItemIssueProcessingPath::resolved_cell(ItemIssueProcessingPath( Some(IssueProcessingPathItem::resolved_cell( IssueProcessingPathItem { file_path: match file_path.into() { diff --git a/turbopack/crates/turbopack-core/src/issue/module.rs b/turbopack/crates/turbopack-core/src/issue/module.rs index 39cb2843c436c..4406fe09f8464 100644 --- a/turbopack/crates/turbopack-core/src/issue/module.rs +++ b/turbopack/crates/turbopack-core/src/issue/module.rs @@ -47,7 +47,7 @@ Read more: https://nextjs.org/docs/app/api-reference/next-config-js/turbo#webpac ) .resolved_cell(), } - .cell() + .resolved_cell() .emit(); Ok(()) diff --git a/turbopack/crates/turbopack-core/src/package_json.rs b/turbopack/crates/turbopack-core/src/package_json.rs index 8610cec81bc1e..28d531b21d860 100644 --- a/turbopack/crates/turbopack-core/src/package_json.rs +++ b/turbopack/crates/turbopack-core/src/package_json.rs @@ -48,7 +48,7 @@ pub async fn read_package_json(path: ResolvedVc) -> Result) -> Result, + self: ResolvedVc, _path: RcStr, _data: Value, ) -> Result> { let this = self.await?; - turbo_tasks::emit(Vc::upcast::>(self)); + turbo_tasks::emit(ResolvedVc::upcast::>(self)); Ok(ContentSourceContent::static_content( this.asset.versioned_content(), )) diff --git a/turbopack/crates/turbopack-dev-server/src/source/conditional.rs b/turbopack/crates/turbopack-dev-server/src/source/conditional.rs index 6ef2d7f9684fc..150d5a471809f 100644 --- a/turbopack/crates/turbopack-dev-server/src/source/conditional.rs +++ b/turbopack/crates/turbopack-dev-server/src/source/conditional.rs @@ -172,11 +172,11 @@ impl GetContentSourceContent for ActivateOnGetContentSource { #[turbo_tasks::function] async fn get( - self: Vc, + self: ResolvedVc, path: RcStr, data: Value, ) -> Result> { - turbo_tasks::emit(Vc::upcast::>(self)); + turbo_tasks::emit(ResolvedVc::upcast::>(self)); Ok(self.await?.get_content.get(path, data)) } } diff --git a/turbopack/crates/turbopack-ecmascript-plugins/src/transform/directives/server.rs b/turbopack/crates/turbopack-ecmascript-plugins/src/transform/directives/server.rs index fcc5e0131abcf..1f6677b574d6b 100644 --- a/turbopack/crates/turbopack-ecmascript-plugins/src/transform/directives/server.rs +++ b/turbopack/crates/turbopack-ecmascript-plugins/src/transform/directives/server.rs @@ -43,7 +43,7 @@ impl CustomTransformer for ServerDirectiveTransformer { UnsupportedServerActionIssue { file_path: ctx.file_path, } - .cell() + .resolved_cell() .emit(); } diff --git a/turbopack/crates/turbopack-ecmascript-plugins/src/transform/swc_ecma_transform_plugins.rs b/turbopack/crates/turbopack-ecmascript-plugins/src/transform/swc_ecma_transform_plugins.rs index f63710fd3f558..1abfb4720509d 100644 --- a/turbopack/crates/turbopack-ecmascript-plugins/src/transform/swc_ecma_transform_plugins.rs +++ b/turbopack/crates/turbopack-ecmascript-plugins/src/transform/swc_ecma_transform_plugins.rs @@ -228,7 +228,7 @@ impl CustomTransformer for SwcEcmaTransformPluginsTransformer { UnsupportedSwcEcmaTransformPluginsIssue { file_path: ctx.file_path, } - .cell() + .resolved_cell() .emit(); } diff --git a/turbopack/crates/turbopack-ecmascript/src/chunk/item.rs b/turbopack/crates/turbopack-ecmascript/src/chunk/item.rs index cc504d1c9afd7..e4c0d3ac9e15f 100644 --- a/turbopack/crates/turbopack-ecmascript/src/chunk/item.rs +++ b/turbopack/crates/turbopack-ecmascript/src/chunk/item.rs @@ -272,7 +272,7 @@ async fn module_factory_with_code_generation_issue( .resolved_cell(), message: StyledString::Text(error_message).resolved_cell(), } - .cell() + .resolved_cell() .emit(); let mut code = CodeBuilder::default(); code += "(() => {{\n\n"; diff --git a/turbopack/crates/turbopack-ecmascript/src/chunk/placeable.rs b/turbopack/crates/turbopack-ecmascript/src/chunk/placeable.rs index da488a555257a..f4aef84104611 100644 --- a/turbopack/crates/turbopack-ecmascript/src/chunk/placeable.rs +++ b/turbopack/crates/turbopack-ecmascript/src/chunk/placeable.rs @@ -69,7 +69,7 @@ async fn side_effects_from_package_json( .resolved_cell(), ), } - .cell() + .resolved_cell() .emit(); None } @@ -91,7 +91,7 @@ async fn side_effects_from_package_json( .resolved_cell(), ), } - .cell() + .resolved_cell() .emit(); Ok(None) } @@ -116,7 +116,7 @@ async fn side_effects_from_package_json( .resolved_cell(), ), } - .cell() + .resolved_cell() .emit(); } } diff --git a/turbopack/crates/turbopack-ecmascript/src/parse.rs b/turbopack/crates/turbopack-ecmascript/src/parse.rs index db09005c08e7d..0c9598de0434b 100644 --- a/turbopack/crates/turbopack-ecmascript/src/parse.rs +++ b/turbopack/crates/turbopack-ecmascript/src/parse.rs @@ -192,7 +192,7 @@ async fn parse_internal( source, error: error.clone(), } - .cell() + .resolved_cell() .emit(); return Ok(ParseResult::Unparseable { @@ -234,7 +234,7 @@ async fn parse_internal( source, error: error.clone(), } - .cell() + .resolved_cell() .emit(); ParseResult::Unparseable { messages: Some(vec![error]), @@ -258,22 +258,19 @@ async fn parse_file_content( transforms: &[EcmascriptInputTransform], ) -> Result> { let source_map: Arc = Default::default(); - let handler = Handler::with_emitter( - true, - false, - Box::new(IssueEmitter::new( - source, - source_map.clone(), - Some("Ecmascript file had an error".into()), - )), + let (emitter, collector) = IssueEmitter::new( + source, + source_map.clone(), + Some("Ecmascript file had an error".into()), ); + let handler = Handler::with_emitter(true, false, Box::new(emitter)); - let emitter = Box::new(IssueEmitter::new( + let (emitter, collector_parse) = IssueEmitter::new( source, source_map.clone(), Some("Parsing ecmascript source code failed".into()), - )); - let parser_handler = Handler::with_emitter(true, false, emitter.clone()); + ); + let parser_handler = Handler::with_emitter(true, false, Box::new(emitter)); let globals = Arc::new(Globals::new()); let globals_ref = &globals; @@ -411,7 +408,7 @@ async fn parse_file_content( .await?; if parser_handler.has_errors() { - let messages = if let Some(error) = emitter.emitted_issues.last() { + let messages = if let Some(error) = collector_parse.last_emitted_issue() { // The emitter created in here only uses StyledString::Text if let StyledString::Text(xx) = &*error.await?.message.await? { Some(vec![xx.clone()]) @@ -462,6 +459,8 @@ async fn parse_file_content( // Assign the correct globals *g = globals; } + collector.emit().await?; + collector_parse.emit().await?; Ok(result.cell()) } diff --git a/turbopack/crates/turbopack-ecmascript/src/references/esm/base.rs b/turbopack/crates/turbopack-ecmascript/src/references/esm/base.rs index e4e83ce83554d..af84e7af18683 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/esm/base.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/esm/base.rs @@ -201,7 +201,7 @@ impl ModuleReference for EsmAssetReference { module, source: self.issue_source, } - .cell() + .resolved_cell() .emit(); } } diff --git a/turbopack/crates/turbopack-ecmascript/src/references/esm/export.rs b/turbopack/crates/turbopack-ecmascript/src/references/esm/export.rs index 956057ec83a07..2d45a5f350076 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/esm/export.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/esm/export.rs @@ -352,27 +352,33 @@ pub async fn expand_star_exports( } } } - EcmascriptExports::None | EcmascriptExports::EmptyCommonJs => emit_star_exports_issue( - asset.ident(), - format!( - "export * used with module {} which has no exports\nTypescript only: Did you \ - want to export only types with `export type * from \"...\"`?\nNote: Using \ - `export type` is more efficient than `export *` as it won't emit any runtime \ - code.", - asset.ident().to_string().await? + EcmascriptExports::None | EcmascriptExports::EmptyCommonJs => { + emit_star_exports_issue( + asset.ident(), + format!( + "export * used with module {} which has no exports\nTypescript only: Did \ + you want to export only types with `export type * from \"...\"`?\nNote: \ + Using `export type` is more efficient than `export *` as it won't emit \ + any runtime code.", + asset.ident().to_string().await? + ) + .into(), ) - .into(), - ), - EcmascriptExports::Value => emit_star_exports_issue( - asset.ident(), - format!( - "export * used with module {} which only has a default export (default export \ - is not exported with export *)\nDid you want to use `export {{ default }} \ - from \"...\";` instead?", - asset.ident().to_string().await? + .await? + } + EcmascriptExports::Value => { + emit_star_exports_issue( + asset.ident(), + format!( + "export * used with module {} which only has a default export (default \ + export is not exported with export *)\nDid you want to use `export {{ \ + default }} from \"...\";` instead?", + asset.ident().to_string().await? + ) + .into(), ) - .into(), - ), + .await? + } EcmascriptExports::CommonJs => { has_dynamic_exports = true; emit_star_exports_issue( @@ -385,7 +391,8 @@ pub async fn expand_star_exports( asset.ident().to_string().await? ) .into(), - ); + ) + .await?; } EcmascriptExports::DynamicNamespace => { has_dynamic_exports = true; @@ -400,7 +407,7 @@ pub async fn expand_star_exports( .cell()) } -fn emit_star_exports_issue(source_ident: Vc, message: RcStr) { +async fn emit_star_exports_issue(source_ident: Vc, message: RcStr) -> Result<()> { AnalyzeIssue::new( IssueSeverity::Warning.cell(), source_ident, @@ -409,7 +416,10 @@ fn emit_star_exports_issue(source_ident: Vc, message: RcStr) { None, None, ) + .to_resolved() + .await? .emit(); + Ok(()) } #[turbo_tasks::value(shared)] diff --git a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs index 0e546668f4748..23ac9bc240d39 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs @@ -590,11 +590,8 @@ pub(crate) async fn analyse_ecmascript_module_internal( } } - let handler = Handler::with_emitter( - true, - false, - Box::new(IssueEmitter::new(source, source_map.clone(), None)), - ); + let (emitter, collector) = IssueEmitter::new(source, source_map.clone(), None); + let handler = Handler::with_emitter(true, false, Box::new(emitter)); let mut var_graph = set_handler_and_globals(&handler, globals, || create_graph(program, eval_context)); @@ -776,7 +773,7 @@ pub(crate) async fn analyse_ecmascript_module_internal( path: source.ident().path().to_resolved().await?, specified_type, } - .cell() + .resolved_cell() .emit(); } @@ -798,7 +795,7 @@ pub(crate) async fn analyse_ecmascript_module_internal( path: source.ident().path().to_resolved().await?, specified_type, } - .cell() + .resolved_cell() .emit(); EcmascriptExports::EsmExports( @@ -856,6 +853,8 @@ pub(crate) async fn analyse_ecmascript_module_internal( None, Some(issue_source(*source, span)), ) + .to_resolved() + .await? .emit(); } @@ -1254,6 +1253,8 @@ pub(crate) async fn analyse_ecmascript_module_internal( analysis.set_successful(true); + collector.emit().await?; + analysis .build(matches!( options.tree_shaking_mode, diff --git a/turbopack/crates/turbopack-ecmascript/src/references/pattern_mapping.rs b/turbopack/crates/turbopack-ecmascript/src/references/pattern_mapping.rs index 1a04e1816beb0..e254b6878315a 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/pattern_mapping.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/pattern_mapping.rs @@ -338,7 +338,7 @@ async fn to_single_pattern_mapping( .resolved_cell(), path: origin.origin_path().to_resolved().await?, } - .cell() + .resolved_cell() .emit(); return Ok(SinglePatternMapping::Invalid); } @@ -368,7 +368,7 @@ async fn to_single_pattern_mapping( .resolved_cell(), path: origin.origin_path().to_resolved().await?, } - .cell() + .resolved_cell() .emit(); Ok(SinglePatternMapping::Invalid) } diff --git a/turbopack/crates/turbopack-ecmascript/src/references/worker.rs b/turbopack/crates/turbopack-ecmascript/src/references/worker.rs index a3f9887e6db83..0381c70ff0386 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/worker.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/worker.rs @@ -76,7 +76,7 @@ impl WorkerAssetReference { .resolved_cell(), path: self.origin.origin_path().to_resolved().await?, } - .cell() + .resolved_cell() .emit(); return Ok(None); }; diff --git a/turbopack/crates/turbopack-ecmascript/src/webpack/references.rs b/turbopack/crates/turbopack-ecmascript/src/webpack/references.rs index 5542e49c37a51..ac473518ee128 100644 --- a/turbopack/crates/turbopack-ecmascript/src/webpack/references.rs +++ b/turbopack/crates/turbopack-ecmascript/src/webpack/references.rs @@ -43,18 +43,16 @@ pub async fn module_references( runtime, transforms, }; - let handler = Handler::with_emitter( - true, - false, - Box::new(IssueEmitter::new( - source, - source_map.clone(), - Some("Parsing webpack bundle failed".into()), - )), + let (emitter, collector) = IssueEmitter::new( + source, + source_map.clone(), + Some("Parsing webpack bundle failed".into()), ); + let handler = Handler::with_emitter(true, false, Box::new(emitter)); HANDLER.set(&handler, || { program.visit_with(&mut visitor); }); + collector.emit().await?; Ok(Vc::cell(references)) } ParseResult::Unparseable { .. } | ParseResult::NotFound => Ok(Vc::cell(Vec::new())), diff --git a/turbopack/crates/turbopack-env/src/try_env.rs b/turbopack/crates/turbopack-env/src/try_env.rs index 7561d528ca813..6480c0d680e57 100644 --- a/turbopack/crates/turbopack-env/src/try_env.rs +++ b/turbopack/crates/turbopack-env/src/try_env.rs @@ -58,7 +58,7 @@ impl ProcessEnv for TryDotenvProcessEnv { description: StyledString::Text(e.root_cause().to_string().into()) .resolved_cell(), } - .cell() + .resolved_cell() .emit(); Ok(prior) } diff --git a/turbopack/crates/turbopack-image/src/process/mod.rs b/turbopack/crates/turbopack-image/src/process/mod.rs index 73ec757a3731a..386cf481cf458 100644 --- a/turbopack/crates/turbopack-image/src/process/mod.rs +++ b/turbopack/crates/turbopack-image/src/process/mod.rs @@ -112,7 +112,7 @@ fn result_to_issue(path: ResolvedVc, result: Result) -> Op issue_severity: None, title: None, } - .cell() + .resolved_cell() .emit(); None } @@ -174,7 +174,7 @@ fn load_image_internal( title: Some(StyledString::Text("AVIF image not supported".into()).resolved_cell()), issue_severity: Some(IssueSeverity::Warning.resolved_cell()), } - .cell() + .resolved_cell() .emit(); return Ok((ImageBuffer::Raw(bytes.to_vec()), format)); } @@ -192,7 +192,7 @@ fn load_image_internal( title: Some(StyledString::Text("WEBP image not supported".into()).resolved_cell()), issue_severity: Some(IssueSeverity::Warning.resolved_cell()), } - .cell() + .resolved_cell() .emit(); return Ok((ImageBuffer::Raw(bytes.to_vec()), format)); } @@ -219,7 +219,7 @@ fn compute_blur_data( issue_severity: None, title: None, } - .cell() + .resolved_cell() .emit(); Some(BlurPlaceholder::fallback()) } diff --git a/turbopack/crates/turbopack-mdx/src/lib.rs b/turbopack/crates/turbopack-mdx/src/lib.rs index 9e2a04378efaf..6e32e1ca4a1ea 100644 --- a/turbopack/crates/turbopack-mdx/src/lib.rs +++ b/turbopack/crates/turbopack-mdx/src/lib.rs @@ -230,7 +230,7 @@ impl MdxTransformedAsset { mdx_rule_id: *err.rule_id, mdx_source: *err.source, } - .cell() + .resolved_cell() .emit(); Ok(MdxTransformResult { diff --git a/turbopack/crates/turbopack-node/src/evaluate.rs b/turbopack/crates/turbopack-node/src/evaluate.rs index 09f1bec3b5bfb..5899446c5292a 100644 --- a/turbopack/crates/turbopack-node/src/evaluate.rs +++ b/turbopack/crates/turbopack-node/src/evaluate.rs @@ -619,7 +619,7 @@ impl EvaluateContext for BasicEvaluateContext { .to_resolved() .await?, } - .cell() + .resolved_cell() .emit(); Ok(()) } diff --git a/turbopack/crates/turbopack-node/src/render/render_proxy.rs b/turbopack/crates/turbopack-node/src/render/render_proxy.rs index 5efc603323899..0f5d09f92c503 100644 --- a/turbopack/crates/turbopack-node/src/render/render_proxy.rs +++ b/turbopack/crates/turbopack-node/src/render/render_proxy.rs @@ -125,7 +125,7 @@ async fn proxy_error( message: StyledString::Text(message.into()).resolved_cell(), status: status.and_then(|status| status.code()), } - .cell() + .resolved_cell() .emit(); Ok((status_code, body)) diff --git a/turbopack/crates/turbopack-node/src/render/render_static.rs b/turbopack/crates/turbopack-node/src/render/render_static.rs index 48f7944361ac9..4408e910461da 100644 --- a/turbopack/crates/turbopack-node/src/render/render_static.rs +++ b/turbopack/crates/turbopack-node/src/render/render_static.rs @@ -173,7 +173,7 @@ async fn static_error( status: status.and_then(|status| status.code()), }; - issue.cell().emit(); + issue.resolved_cell().emit(); let html = fallback_page.with_body(body.into()); diff --git a/turbopack/crates/turbopack-node/src/transforms/webpack.rs b/turbopack/crates/turbopack-node/src/transforms/webpack.rs index 7c93eaafa9b9f..72a4405fca06b 100644 --- a/turbopack/crates/turbopack-node/src/transforms/webpack.rs +++ b/turbopack/crates/turbopack-node/src/transforms/webpack.rs @@ -454,7 +454,7 @@ impl EvaluateContext for WebpackLoaderContext { .to_resolved() .await?, } - .cell() + .resolved_cell() .emit(); Ok(()) } @@ -478,7 +478,7 @@ impl EvaluateContext for WebpackLoaderContext { context_ident: self.context_ident_for_issue, path: self.cwd.join(path).to_resolved().await?, } - .cell() + .resolved_cell() .emit(); } InfoMessage::DirDependency { path, glob } => { @@ -504,7 +504,7 @@ impl EvaluateContext for WebpackLoaderContext { .to_resolved() .await?, } - .cell() + .resolved_cell() .emit(); } InfoMessage::Log(log) => { @@ -600,7 +600,7 @@ impl EvaluateContext for WebpackLoaderContext { .to_resolved() .await?, } - .cell() + .resolved_cell() .emit(); } Ok(()) diff --git a/turbopack/crates/turbopack-resolve/src/typescript.rs b/turbopack/crates/turbopack-resolve/src/typescript.rs index 66bf067640b50..45c103f4014cc 100644 --- a/turbopack/crates/turbopack-resolve/src/typescript.rs +++ b/turbopack/crates/turbopack-resolve/src/typescript.rs @@ -76,7 +76,7 @@ pub async fn read_tsconfigs( source_ident: tsconfig.ident().to_resolved().await?, message: message.into(), } - .cell() + .resolved_cell() .emit(); } FileJsonContent::NotFound => { @@ -85,7 +85,7 @@ pub async fn read_tsconfigs( source_ident: tsconfig.ident().to_resolved().await?, message: "tsconfig not found".into(), } - .cell() + .resolved_cell() .emit(); } FileJsonContent::Content(json) => { @@ -103,7 +103,7 @@ pub async fn read_tsconfigs( message: format!("extends: \"{}\" doesn't resolve correctly", extends) .into(), } - .cell() + .resolved_cell() .emit(); } } @@ -308,7 +308,7 @@ pub async fn tsconfig_resolve_options( ) .into(), } - .cell() + .resolved_cell() .emit() } } diff --git a/turbopack/crates/turbopack-swc-utils/Cargo.toml b/turbopack/crates/turbopack-swc-utils/Cargo.toml index aa8afc4798c75..8f9bfdbdd9ee3 100644 --- a/turbopack/crates/turbopack-swc-utils/Cargo.toml +++ b/turbopack/crates/turbopack-swc-utils/Cargo.toml @@ -13,6 +13,8 @@ bench = false workspace = true [dependencies] +anyhow = { workspace = true } +parking_lot = { workspace = true } turbo-rcstr = { workspace = true } turbo-tasks = { workspace = true } turbopack-core = { workspace = true } diff --git a/turbopack/crates/turbopack-swc-utils/src/emitter.rs b/turbopack/crates/turbopack-swc-utils/src/emitter.rs index 1ae371a487912..5977e287d2c25 100644 --- a/turbopack/crates/turbopack-swc-utils/src/emitter.rs +++ b/turbopack/crates/turbopack-swc-utils/src/emitter.rs @@ -1,5 +1,7 @@ -use std::sync::Arc; +use std::{mem::take, sync::Arc}; +use anyhow::Result; +use parking_lot::Mutex; use swc_core::common::{ errors::{DiagnosticBuilder, DiagnosticId, Emitter, Level}, source_map::SmallPos, @@ -12,12 +14,54 @@ use turbopack_core::{ source::Source, }; -#[derive(Clone)] +pub struct IssueCollector { + inner: Arc>, +} + +impl IssueCollector { + pub async fn emit(self) -> Result<()> { + let issues = { + let mut inner = self.inner.lock(); + if inner.emitted { + return Ok(()); + } + inner.emitted = true; + take(&mut inner.emitted_issues) + }; + + for issue in issues { + issue.to_resolved().await?.emit(); + } + Ok(()) + } + + pub fn last_emitted_issue(&self) -> Option> { + let inner = self.inner.lock(); + inner.emitted_issues.last().copied() + } +} + +struct IssueCollectorInner { + emitted_issues: Vec>, + emitted: bool, +} + +impl Drop for IssueCollectorInner { + fn drop(&mut self) { + if !self.emitted { + panic!( + "IssueCollector and IssueEmitter were dropped without calling \ + `collector.emit().await?`" + ); + } + } +} + pub struct IssueEmitter { pub source: ResolvedVc>, pub source_map: Arc, pub title: Option, - pub emitted_issues: Vec>, + inner: Arc>, } impl IssueEmitter { @@ -25,13 +69,20 @@ impl IssueEmitter { source: ResolvedVc>, source_map: Arc, title: Option, - ) -> Self { - Self { - source, - source_map, - title, + ) -> (Self, IssueCollector) { + let inner = Arc::new(Mutex::new(IssueCollectorInner { emitted_issues: vec![], - } + emitted: false, + })); + ( + Self { + source, + source_map, + title, + inner: inner.clone(), + }, + IssueCollector { inner }, + ) } } @@ -92,8 +143,8 @@ impl Emitter for IssueEmitter { source, ); - self.emitted_issues.push(issue); - - issue.emit(); + let mut inner = self.inner.lock(); + inner.emitted = false; + inner.emitted_issues.push(issue); } } diff --git a/turbopack/crates/turbopack-tests/tests/execution/turbopack/async-modules/export-all/issues/unexpected export __star__-1b6874.txt b/turbopack/crates/turbopack-tests/tests/execution/turbopack/async-modules/export-all/issues/unexpected export __star__-9b505f.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/execution/turbopack/async-modules/export-all/issues/unexpected export __star__-1b6874.txt rename to turbopack/crates/turbopack-tests/tests/execution/turbopack/async-modules/export-all/issues/unexpected export __star__-9b505f.txt diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1001__ import(FreeVar(Math)[__quo__ra-d3b7e2.txt b/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1001__ import(FreeVar(Math)[__quo__ra-5994a8.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1001__ import(FreeVar(Math)[__quo__ra-d3b7e2.txt rename to turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1001__ import(FreeVar(Math)[__quo__ra-5994a8.txt diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1002__ require(FreeVar(Math)[__quo__r-6e3023.txt b/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1002__ require(FreeVar(Math)[__quo__r-ae8b1d.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1002__ require(FreeVar(Math)[__quo__r-6e3023.txt rename to turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1002__ require(FreeVar(Math)[__quo__r-ae8b1d.txt diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1004__ fs.readFileSync(FreeVar(Math)[-d1bdaa.txt b/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1004__ fs.readFileSync(FreeVar(Math)[-9b8ecf.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1004__ fs.readFileSync(FreeVar(Math)[-d1bdaa.txt rename to turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1004__ fs.readFileSync(FreeVar(Math)[-9b8ecf.txt diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1004__ fs.readFileSync(FreeVar(Math)[-6979f9.txt b/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1004__ fs.readFileSync(FreeVar(Math)[-ad123b.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1004__ fs.readFileSync(FreeVar(Math)[-6979f9.txt rename to turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1004__ fs.readFileSync(FreeVar(Math)[-ad123b.txt diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(FreeVa-affa1e.txt b/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(FreeVa-5687e7.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(FreeVa-affa1e.txt rename to turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(FreeVa-5687e7.txt diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(__-10f2d3.txt b/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(__-e5d6ef.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(__-10f2d3.txt rename to turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(__-e5d6ef.txt diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(__quo_-148671.txt b/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(__quo_-6d6a3b.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(__quo_-148671.txt rename to turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1005__ child_process.spawnSync(__quo_-6d6a3b.txt diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1201__ new URL(FreeVar(Math)[__quo__r-6f3f56.txt b/turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1201__ new URL(FreeVar(Math)[__quo__r-9d8616.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1201__ new URL(FreeVar(Math)[__quo__r-6f3f56.txt rename to turbopack/crates/turbopack-tests/tests/snapshot/dynamic-request/very-dynamic/issues/__l___lint TP1201__ new URL(FreeVar(Math)[__quo__r-9d8616.txt diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/issues/unexpected export __star__-fec6f9.txt b/turbopack/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/issues/unexpected export __star__-f9a205.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/issues/unexpected export __star__-fec6f9.txt rename to turbopack/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/issues/unexpected export __star__-f9a205.txt diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/issues/unexpected export __star__-951920.txt b/turbopack/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/issues/unexpected export __star__-13c450.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/issues/unexpected export __star__-951920.txt rename to turbopack/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/issues/unexpected export __star__-13c450.txt diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/imports/duplicate-binding/issues/Ecmascript file had an error-a1afab.txt b/turbopack/crates/turbopack-tests/tests/snapshot/imports/duplicate-binding/issues/Ecmascript file had an error-f62e84.txt similarity index 100% rename from turbopack/crates/turbopack-tests/tests/snapshot/imports/duplicate-binding/issues/Ecmascript file had an error-a1afab.txt rename to turbopack/crates/turbopack-tests/tests/snapshot/imports/duplicate-binding/issues/Ecmascript file had an error-f62e84.txt diff --git a/turbopack/crates/turbopack/src/lib.rs b/turbopack/crates/turbopack/src/lib.rs index efedcda427af1..6d2e5c66f2016 100644 --- a/turbopack/crates/turbopack/src/lib.rs +++ b/turbopack/crates/turbopack/src/lib.rs @@ -609,7 +609,7 @@ async fn process_default_internal( ) .resolved_cell(), } - .cell() + .resolved_cell() .emit(); Some(module_type) } @@ -625,7 +625,7 @@ async fn process_default_internal( ) .resolved_cell(), } - .cell() + .resolved_cell() .emit(); None } diff --git a/turbopack/crates/turbopack/src/unsupported_sass.rs b/turbopack/crates/turbopack/src/unsupported_sass.rs index a45453f1a4fe1..08ed1e7602103 100644 --- a/turbopack/crates/turbopack/src/unsupported_sass.rs +++ b/turbopack/crates/turbopack/src/unsupported_sass.rs @@ -48,7 +48,7 @@ impl AfterResolvePlugin for UnsupportedSassResolvePlugin { file_path: lookup_path, request, } - .cell() + .resolved_cell() .emit(); }