Skip to content

Commit 2727379

Browse files
committed
improve error reporting
1 parent fa83b90 commit 2727379

File tree

8 files changed

+97
-77
lines changed

8 files changed

+97
-77
lines changed

crates/turbo-tasks-memory/src/memory_backend.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -357,14 +357,7 @@ impl Backend for MemoryBackend {
357357
turbo_tasks,
358358
|output| {
359359
Task::add_dependency_to_current(TaskDependency::TaskOutput(task));
360-
output.read(reader).map_err(|err| {
361-
self.with_task(task, |task| {
362-
if let Some(name) = task.get_function_name() {
363-
return err.context(format!("Reading output from {name} failed"));
364-
}
365-
err
366-
})
367-
})
360+
output.read(reader)
368361
},
369362
)
370363
}

crates/turbo-tasks-memory/src/task.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,12 @@ impl Task {
442442

443443
pub(crate) fn get_function_name(&self) -> Option<&'static str> {
444444
if let TaskType::Persistent(ty) = &self.ty {
445-
if let PersistentTaskType::Native(native_fn, _) = &**ty {
446-
return Some(&registry::get_function(*native_fn).name);
445+
match &**ty {
446+
PersistentTaskType::Native(native_fn, _)
447+
| PersistentTaskType::ResolveNative(native_fn, _) => {
448+
return Some(&registry::get_function(*native_fn).name);
449+
}
450+
_ => {}
447451
}
448452
}
449453
None

crates/turbopack-ecmascript/src/chunk/mod.rs

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,36 @@ impl EcmascriptChunkContentEntryVc {
491491
#[turbo_tasks::function]
492492
async fn new(chunk_item: EcmascriptChunkItemVc) -> Result<Self> {
493493
let content = chunk_item.content();
494-
let factory = module_factory(content, chunk_item);
494+
let factory = match module_factory(content).resolve().await {
495+
Ok(factory) => factory,
496+
Err(error) => {
497+
let id = chunk_item.id().to_string().await;
498+
let id = id.as_ref().map_or_else(|_| "unknown", |id| &**id);
499+
let mut error_message =
500+
format!("An error occurred while generating the chunk item {}", id);
501+
for err in error.chain() {
502+
write!(error_message, "\n at {}", err)?;
503+
}
504+
let js_error_message = serde_json::to_string(&error_message)?;
505+
let issue = CodeGenerationIssue {
506+
severity: IssueSeverity::Error.cell(),
507+
path: chunk_item.related_path(),
508+
title: StringVc::cell("Code generation for chunk item errored".to_string()),
509+
message: StringVc::cell(error_message),
510+
}
511+
.cell();
512+
issue.as_issue().emit();
513+
let mut code = CodeBuilder::default();
514+
code += "(() => {{\n\n";
515+
write!(
516+
code,
517+
"throw new Error({error});\n",
518+
error = &js_error_message
519+
)?;
520+
code += "\n}})";
521+
code.build().cell()
522+
}
523+
};
495524
let id = chunk_item.id().await?;
496525
let code = factory.await?;
497526
let hash = hash_xxh3_hash64(code.source_code());
@@ -507,40 +536,8 @@ impl EcmascriptChunkContentEntryVc {
507536
}
508537

509538
#[turbo_tasks::function]
510-
async fn module_factory(
511-
content: EcmascriptChunkItemContentVc,
512-
chunk_item: EcmascriptChunkItemVc,
513-
) -> Result<CodeVc> {
514-
let content = match content.await {
515-
Ok(content) => content,
516-
Err(error) => {
517-
let id = chunk_item.id().to_string().await;
518-
let id = id.as_ref().map_or_else(|_| "unknown", |id| &**id);
519-
let mut error_message =
520-
format!("An error occurred while generating the chunk item {}", id);
521-
for err in error.chain() {
522-
write!(error_message, "\n at {}", err)?;
523-
}
524-
let js_error_message = serde_json::to_string(&error_message)?;
525-
let issue = CodeGenerationIssue {
526-
severity: IssueSeverity::Error.cell(),
527-
path: chunk_item.related_path(),
528-
title: StringVc::cell("Code generation for chunk item errored".to_string()),
529-
message: StringVc::cell(error_message),
530-
}
531-
.cell();
532-
issue.as_issue().emit();
533-
let mut code = CodeBuilder::default();
534-
code += "(() => {{\n\n";
535-
write!(
536-
code,
537-
"throw new Error({error});\n",
538-
error = &js_error_message
539-
)?;
540-
code += "\n}})";
541-
return Ok(code.build().cell());
542-
}
543-
};
539+
async fn module_factory(content: EcmascriptChunkItemContentVc) -> Result<CodeVc> {
540+
let content = content.await?;
544541
let mut args = vec![
545542
"r: __turbopack_require__",
546543
"x: __turbopack_external_require__",

crates/turbopack-json/src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
88
#![feature(min_specialization)]
99

10-
use anyhow::Result;
10+
use anyhow::{Context, Result};
1111
use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc};
1212
use turbo_tasks_fs::FileSystemPathVc;
1313
use turbopack_core::{
@@ -110,7 +110,13 @@ impl EcmascriptChunkItem for JsonChunkItem {
110110
async fn content(&self) -> Result<EcmascriptChunkItemContentVc> {
111111
// We parse to JSON and then stringify again to ensure that the
112112
// JSON is valid.
113-
let content = self.module.path().read_json().to_string().await?;
113+
let content = self
114+
.module
115+
.path()
116+
.read_json()
117+
.to_string()
118+
.await
119+
.context("Unable to make a module from invalid JSON")?;
114120
let js_str_content = serde_json::to_string(content.as_str())?;
115121
let inner_code = format!("__turbopack_export_value__(JSON.parse({js_str_content}));");
116122
Ok(EcmascriptChunkItemContent {

crates/turbopack-tests/tests/snapshot.rs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use once_cell::sync::Lazy;
1111
use serde::Deserialize;
1212
use similar::TextDiff;
1313
use test_generator::test_resources;
14-
use turbo_tasks::{debug::ValueDebug, NothingVc, TryJoinIterExt, TurboTasks, Value};
14+
use turbo_tasks::{debug::ValueDebug, NothingVc, TryJoinIterExt, TurboTasks, Value, ValueToString};
1515
use turbo_tasks_env::DotenvProcessEnvVc;
1616
use turbo_tasks_fs::{
1717
util::sys_to_unix, DirectoryContent, DirectoryEntry, DiskFileSystemVc, File, FileContent,
@@ -101,7 +101,9 @@ async fn run(resource: &'static str) -> Result<()> {
101101
let tt = TurboTasks::new(MemoryBackend::default());
102102
let task = tt.spawn_once_task(async move {
103103
let out = run_test(resource.to_string());
104-
handle_issues(out).await?;
104+
handle_issues(out)
105+
.await
106+
.context("Unable to handle issues")?;
105107
Ok(NothingVc::new().into())
106108
});
107109
tt.wait_task_completion(task, true).await?;
@@ -238,10 +240,17 @@ async fn run_test(resource: String) -> Result<FileSystemPathVc> {
238240
}
239241

240242
while let Some(asset) = queue.pop_front() {
241-
walk_asset(asset, &mut seen, &mut queue).await?;
243+
walk_asset(asset, &mut seen, &mut queue)
244+
.await
245+
.context(format!(
246+
"Failed to walk asset {}",
247+
asset.path().to_string().await.context("to_string failed")?
248+
))?;
242249
}
243250

244-
matches_expected(expected_paths, seen).await?;
251+
matches_expected(expected_paths, seen)
252+
.await
253+
.context("Actual assets doesn't match with expected assets")?;
245254

246255
Ok(path)
247256
}
@@ -273,28 +282,38 @@ async fn walk_asset(
273282
Ok(())
274283
}
275284

276-
async fn get_contents(file: AssetContentVc) -> Result<Option<String>> {
277-
Ok(match &*file.await? {
278-
AssetContent::File(file) => match &*file.await? {
279-
FileContent::NotFound => None,
280-
FileContent::Content(expected) => Some(expected.content().to_str()?.trim().to_string()),
285+
async fn get_contents(file: AssetContentVc, path: FileSystemPathVc) -> Result<Option<String>> {
286+
Ok(
287+
match &*file.await.context(format!(
288+
"Unable to read AssetContent of {}",
289+
path.to_string().await?
290+
))? {
291+
AssetContent::File(file) => match &*file.await.context(format!(
292+
"Unable to read FileContent of {}",
293+
path.to_string().await?
294+
))? {
295+
FileContent::NotFound => None,
296+
FileContent::Content(expected) => {
297+
Some(expected.content().to_str()?.trim().to_string())
298+
}
299+
},
300+
AssetContent::Redirect { target, link_type } => Some(format!(
301+
"Redirect {{ target: {target}, link_type: {:?} }}",
302+
link_type
303+
)),
281304
},
282-
AssetContent::Redirect { target, link_type } => Some(format!(
283-
"Redirect {{ target: {target}, link_type: {:?} }}",
284-
link_type
285-
)),
286-
})
305+
)
287306
}
288307

289308
async fn diff(path: FileSystemPathVc, actual: AssetContentVc) -> Result<()> {
290309
let path_str = &path.await?.path;
291310
let expected = path.read().into();
292311

293-
let actual = match get_contents(actual).await? {
312+
let actual = match get_contents(actual, path).await? {
294313
Some(s) => s,
295314
None => bail!("could not generate {} contents", path_str),
296315
};
297-
let expected = get_contents(expected).await?;
316+
let expected = get_contents(expected, path).await?;
298317

299318
if Some(&actual) != expected.as_ref() {
300319
if *UPDATE {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
PlainIssue {
2+
severity: Error,
3+
context: "[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json",
4+
category: "code generation",
5+
title: "Code generation for chunk item errored",
6+
description: "An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n at Execution of module_factory failed\n at Execution of JsonChunkItem::content failed\n at Unable to make a module from invalid JSON\n at Execution of FileJsonContent::to_string failed\n at File is not valid JSON",
7+
detail: "",
8+
documentation_link: "",
9+
source: None,
10+
sub_issues: [],
11+
}

crates/turbopack-tests/tests/snapshot/imports/json/issues/Error parsing JSON file-f0508c.txt

Lines changed: 0 additions & 11 deletions
This file was deleted.

crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_e24981.js

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)