Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions crates/next-api/src/module_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,14 +568,7 @@ async fn validate_pages_css_imports(
.map(async |issue| {
// We allow imports of global CSS files which are inside of `node_modules`.
Ok(
if !issue
.module
.ident()
.path()
.await?
.path
.contains("/node_modules/")
{
if !issue.module.ident().path().await?.is_in_node_modules() {
Some(issue)
} else {
None
Expand Down
4 changes: 4 additions & 0 deletions turbopack/crates/turbo-tasks-fs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,10 @@ impl FileSystemPath {
self.path.is_empty()
}

pub fn is_in_node_modules(&self) -> bool {
self.path.starts_with("node_modules/") || self.path.contains("/node_modules/")
}

/// Returns the path of `inner` relative to `self`.
///
/// Note: this method always strips the leading `/` from the result.
Expand Down
178 changes: 87 additions & 91 deletions turbopack/crates/turbopack-ecmascript/src/references/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -974,12 +974,7 @@ async fn analyze_ecmascript_module_internal(
origin,
compile_time_info,
var_graph: &var_graph,
allow_project_root_tracing: !source
.ident()
.path()
.await?
.path
.contains("/node_modules/"),
allow_project_root_tracing: !source.ident().path().await?.is_in_node_modules(),
fun_args_values: Default::default(),
var_cache: Default::default(),
first_import_meta: true,
Expand Down Expand Up @@ -1742,15 +1737,21 @@ async fn handle_call<G: Fn(Vec<Effect>) + Send + Sync>(
return Ok(());
}

let get_traced_project_dir = async || {
let get_traced_project_dir = async || -> Result<FileSystemPath> {
// readFileSync("./foo") should always be relative to the project root, but this is
// dangerous inside of node_modules as it can cause a lot of false positives in the
// tracing, if some package does `path.join(dynamic)`, it would include everything from
// the project root as well.
if allow_project_root_tracing {
compile_time_info.environment().cwd().owned().await
// dangerous inside of node_modules as it can cause a lot of false positives in the tracing,
// if some package does `path.join(dynamic)`, it would include everything from the project
// root as well.
//
// Also, when there's no cwd set (i.e. in a tracing-specific module context, as we shouldn't
// assume a `process.cwd()` for all of node_modules), fallback to the source file directory.
// This still allows relative file accesses, just not from the project root.
if allow_project_root_tracing
&& let Some(cwd) = compile_time_info.environment().cwd().owned().await?
{
Ok(cwd)
} else {
Ok(Some(source.ident().path().await?.parent()))
Ok(source.ident().path().await?.parent())
}
};

Expand Down Expand Up @@ -1982,18 +1983,16 @@ async fn handle_call<G: Fn(Vec<Effect>) + Send + Sync>(
return Ok(());
}
}
if let Some(context_dir) = get_traced_project_dir().await? {
analysis.add_reference(
FileSourceReference::new(
context_dir,
Pattern::new(pat),
collect_affecting_sources,
make_issue_source(),
)
.to_resolved()
.await?,
);
}
analysis.add_reference(
FileSourceReference::new(
get_traced_project_dir().await?,
Pattern::new(pat),
collect_affecting_sources,
make_issue_source(),
)
.to_resolved()
.await?,
);
return Ok(());
}
let (args, hints) = explain_args(&args);
Expand Down Expand Up @@ -2038,13 +2037,15 @@ async fn handle_call<G: Fn(Vec<Effect>) + Send + Sync>(
return Ok(());
}
}
if let Some(context_dir) = get_traced_project_dir().await? {
analysis.add_reference(
DirAssetReference::new(context_dir, Pattern::new(pat), make_issue_source())
.to_resolved()
.await?,
);
}
analysis.add_reference(
DirAssetReference::new(
get_traced_project_dir().await?,
Pattern::new(pat),
make_issue_source(),
)
.to_resolved()
.await?,
);
return Ok(());
}

Expand Down Expand Up @@ -2080,13 +2081,15 @@ async fn handle_call<G: Fn(Vec<Effect>) + Send + Sync>(
return Ok(());
}
}
if let Some(context_dir) = get_traced_project_dir().await? {
analysis.add_reference(
DirAssetReference::new(context_dir, Pattern::new(pat), make_issue_source())
.to_resolved()
.await?,
);
}
analysis.add_reference(
DirAssetReference::new(
get_traced_project_dir().await?,
Pattern::new(pat),
make_issue_source(),
)
.to_resolved()
.await?,
);
return Ok(());
}
JsValue::WellKnownFunction(WellKnownFunctionKind::ChildProcessSpawnMethod(name))
Expand Down Expand Up @@ -2130,12 +2133,10 @@ async fn handle_call<G: Fn(Vec<Effect>) + Send + Sync>(
if dynamic {
show_dynamic_warning = true;
}
if (!dynamic || !ignore_dynamic_requests)
&& let Some(context_dir) = get_traced_project_dir().await?
{
if !dynamic || !ignore_dynamic_requests {
analysis.add_reference(
FileSourceReference::new(
context_dir,
get_traced_project_dir().await?,
Pattern::new(pat),
collect_affecting_sources,
IssueSource::from_swc_offsets(
Expand Down Expand Up @@ -2371,17 +2372,15 @@ async fn handle_call<G: Fn(Vec<Effect>) + Send + Sync>(
.await?;
js_value_to_pattern(&linked_func_call)
};
if let Some(context_dir) = get_traced_project_dir().await? {
analysis.add_reference(
DirAssetReference::new(
context_dir,
Pattern::new(abs_pattern),
make_issue_source(),
)
.to_resolved()
.await?,
);
}
analysis.add_reference(
DirAssetReference::new(
get_traced_project_dir().await?,
Pattern::new(abs_pattern),
make_issue_source(),
)
.to_resolved()
.await?,
);
return Ok(());
}
}
Expand Down Expand Up @@ -2440,17 +2439,15 @@ async fn handle_call<G: Fn(Vec<Effect>) + Send + Sync>(
.await?;
js_value_to_pattern(&linked_func_call)
};
if let Some(context_dir) = get_traced_project_dir().await? {
analysis.add_reference(
DirAssetReference::new(
context_dir,
Pattern::new(abs_pattern),
make_issue_source(),
)
.to_resolved()
.await?,
);
}
analysis.add_reference(
DirAssetReference::new(
get_traced_project_dir().await?,
Pattern::new(abs_pattern),
make_issue_source(),
)
.to_resolved()
.await?,
);
return Ok(());
}
let (args, hints) = explain_args(&args);
Expand Down Expand Up @@ -2498,33 +2495,32 @@ async fn handle_call<G: Fn(Vec<Effect>) + Send + Sync>(
if args.len() == 2
&& let Some(JsValue::Object { parts, .. }) = args.get(1)
{
if let Some(context_dir) = get_traced_project_dir().await? {
let resolved_dirs = parts
.iter()
.filter_map(|object_part| match object_part {
ObjectPart::KeyValue(
JsValue::Constant(key),
JsValue::Array { items: dirs, .. },
) if key.as_str() == Some("includeDirs") => {
Some(dirs.iter().filter_map(|dir| dir.as_str()))
}
_ => None,
})
.flatten()
.map(|dir| {
DirAssetReference::new(
context_dir.clone(),
Pattern::new(Pattern::Constant(dir.into())),
make_issue_source(),
)
.to_resolved()
})
.try_join()
.await?;
let context_dir = get_traced_project_dir().await?;
let resolved_dirs = parts
.iter()
.filter_map(|object_part| match object_part {
ObjectPart::KeyValue(
JsValue::Constant(key),
JsValue::Array { items: dirs, .. },
) if key.as_str() == Some("includeDirs") => {
Some(dirs.iter().filter_map(|dir| dir.as_str()))
}
_ => None,
})
.flatten()
.map(|dir| {
DirAssetReference::new(
context_dir.clone(),
Pattern::new(Pattern::Constant(dir.into())),
make_issue_source(),
)
.to_resolved()
})
.try_join()
.await?;

for resolved_dir_ref in resolved_dirs {
analysis.add_reference(resolved_dir_ref);
}
for resolved_dir_ref in resolved_dirs {
analysis.add_reference(resolved_dir_ref);
}

return Ok(());
Expand Down
Loading