Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

15.1 docs: Add experimental tags to forbidden and unauthorized APIs #73513

Merged
merged 1 commit into from
Dec 10, 2024
Merged
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
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ description: API reference for the forbidden.js special file.
related:
links:
- app/api-reference/functions/forbidden
version: canary
version: experimental
---

The **forbidden** file is used to render UI when the [`forbidden`](/docs/app/api-reference/functions/forbidden) function is invoked during authentication. Along with allowing you to customize the UI, Next.js will return a `403` status code.
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ description: API reference for the unauthorized.js special file.
related:
links:
- app/api-reference/functions/unauthorized
version: canary
version: experimental
---

The **unauthorized** file is used to render UI when the [`unauthorized`](/docs/app/api-reference/functions/unauthorized) function is invoked during authentication. Along with allowing you to customize the UI, Next.js will return a `401` status code.
2 changes: 1 addition & 1 deletion docs/01-app/03-api-reference/04-functions/forbidden.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: forbidden
description: API Reference for the forbidden function.
version: canary
version: experimental
related:
links:
- app/api-reference/file-conventions/forbidden
2 changes: 1 addition & 1 deletion docs/01-app/03-api-reference/04-functions/unauthorized.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: unauthorized
description: API Reference for the unauthorized function.
version: canary
version: experimental
related:
links:
- app/api-reference/file-conventions/unauthorized

Unchanged files with check annotations Beta

#[derive(Debug)]
#[turbo_tasks::value]
pub struct CapturedDiagnostics {
pub diagnostics: auto_hash_map::AutoSet<Vc<Box<dyn Diagnostic>>>,

Check warning on line 114 in turbopack/crates/turbopack-core/src/diagnostics/mod.rs

GitHub Actions / ast-grep lint

no-vc-struct

Don't use a Vc directly in a struct
}
}
#[turbo_tasks::value(transparent)]
pub struct OptionSourceMap(Option<Vc<SourceMap>>);

Check warning on line 61 in turbopack/crates/turbopack-core/src/source_map/mod.rs

GitHub Actions / ast-grep lint

no-vc-struct

Don't use a Vc directly in a struct
#[turbo_tasks::value_impl]
impl OptionSourceMap {
#[turbo_tasks::value]
#[derive(Clone, Debug)]
pub struct TokenWithSource {
pub token: Vc<Token>,

Check warning on line 95 in turbopack/crates/turbopack-core/src/source_map/mod.rs

GitHub Actions / ast-grep lint

no-vc-struct

Don't use a Vc directly in a struct
pub source_content: Option<Vc<Box<dyn Source>>>,

Check warning on line 96 in turbopack/crates/turbopack-core/src/source_map/mod.rs

GitHub Actions / ast-grep lint

no-vc-struct

Don't use a Vc directly in a struct
}
/// A SyntheticToken represents a region of the generated file that was created
/// Multiple [ModuleReference]s
#[turbo_tasks::value(transparent)]
pub struct ModuleReferences(Vec<Vc<Box<dyn ModuleReference>>>);

Check warning on line 37 in turbopack/crates/turbopack-core/src/reference/mod.rs

GitHub Actions / ast-grep lint

no-vc-struct

Don't use a Vc directly in a struct
#[turbo_tasks::value_impl]
impl ModuleReferences {
#[turbo_tasks::value]
pub struct SingleModuleReference {
asset: ResolvedVc<Box<dyn Module>>,
description: Vc<RcStr>,

Check warning on line 52 in turbopack/crates/turbopack-core/src/reference/mod.rs

GitHub Actions / ast-grep lint

no-vc-struct

Don't use a Vc directly in a struct
}
#[turbo_tasks::value_impl]
#[turbo_tasks::value]
pub struct SingleChunkableModuleReference {
asset: ResolvedVc<Box<dyn Module>>,
description: Vc<RcStr>,

Check warning on line 90 in turbopack/crates/turbopack-core/src/reference/mod.rs

GitHub Actions / ast-grep lint

no-vc-struct

Don't use a Vc directly in a struct
}
#[turbo_tasks::value_impl]
#[turbo_tasks::value]
pub struct SingleOutputAssetReference {
asset: ResolvedVc<Box<dyn OutputAsset>>,
description: Vc<RcStr>,

Check warning on line 129 in turbopack/crates/turbopack-core/src/reference/mod.rs

GitHub Actions / ast-grep lint

no-vc-struct

Don't use a Vc directly in a struct
}
#[turbo_tasks::value_impl]
.map(|r| r.resolve_reference())
.try_join()
.await?;
for resolve_result in resolve_results {
modules.extend(resolve_result.primary_modules_raw_iter());
modules.extend(
resolve_result
.affecting_sources_iter()
.map(|source| async move {
Ok(ResolvedVc::upcast(
RawModule::new(*source).to_resolved().await?,
))
})
.try_join()
.await?,
);
}

Check notice on line 193 in turbopack/crates/turbopack-core/src/reference/mod.rs

GitHub Actions / ast-grep lint

to-resolved-in-loop

Calling `RawModule::new(*source).to_resolved().await?` in a loop could be a doing a lot of work sequentially. Consider producing an iterator of futures and using `try_join`.
let resolved_modules: FxIndexSet<_> = modules.into_iter().collect();
/// Next.js apps.
#[turbo_tasks::value]
pub struct ProxiedAsset {
asset: Vc<Box<dyn OutputAsset>>,

Check warning on line 18 in turbopack/crates/turbopack-core/src/proxied_asset.rs

GitHub Actions / ast-grep lint

no-vc-struct

Don't use a Vc directly in a struct
path: Vc<FileSystemPath>,

Check warning on line 19 in turbopack/crates/turbopack-core/src/proxied_asset.rs

GitHub Actions / ast-grep lint

no-vc-struct

Don't use a Vc directly in a struct
}
#[turbo_tasks::value_impl]
refs: &mut Vec<ResolvedVc<Box<dyn Source>>>,
) -> Result<Option<ResolvedVc<FileSystemPath>>> {
let result = fs_path.resolve().await?.realpath_with_links().await?;
for path in result.symlinks.iter() {
refs.push(ResolvedVc::upcast(
FileSource::new(**path).to_resolved().await?,
));
}

Check notice on line 1066 in turbopack/crates/turbopack-core/src/resolve/mod.rs

GitHub Actions / ast-grep lint

to-resolved-in-loop

Calling `FileSource::new(**path).to_resolved().await?` in a loop could be a doing a lot of work sequentially. Consider producing an iterator of futures and using `try_join`.
let path = result.path;
Ok(if *path.get_type().await? == ty {
Some(path)
refs: &mut Vec<ResolvedVc<Box<dyn Source>>>,
) -> Result<Option<(FileSystemEntryType, Vc<FileSystemPath>)>> {
let result = fs_path.resolve().await?.realpath_with_links().await?;
for path in result.symlinks.iter() {
refs.push(ResolvedVc::upcast(
FileSource::new(**path).to_resolved().await?,
));
}

Check notice on line 1084 in turbopack/crates/turbopack-core/src/resolve/mod.rs

GitHub Actions / ast-grep lint

to-resolved-in-loop

Calling `FileSource::new(**path).to_resolved().await?` in a loop could be a doing a lot of work sequentially. Consider producing an iterator of futures and using `try_join`.
let path = result.path;
let ty = *path.get_type().await?;
Ok(
fragment: Vc<RcStr>,
) -> Result<Option<Vc<ResolveResult>>> {
// Check alias field for module aliases first
for in_package in options_value.in_package.iter() {
// resolve_module_request is called when importing a node
// module, not a PackageInternal one, so the imports field
// doesn't apply.
let ResolveInPackage::AliasField(field) = in_package else {
continue;
};
let FindContextFileResult::Found(package_json_path, refs) =
&*find_context_file(lookup_path, package_json().resolve().await?).await?
else {
continue;
};
let read = read_package_json(**package_json_path).await?;
let Some(package_json) = &*read else {
continue;
};
let Some(field_value) = package_json[field.as_str()].as_object() else {
continue;
};
let package_path = package_json_path.parent().resolve().await?;
let Some(request) = get_request(&*package_path.await?) else {
continue;
};
let value = if let Some(value) = field_value.get(&*request) {
value
} else if let Some(request) = request.strip_prefix("./") {
let Some(value) = field_value.get(request) else {
continue;
};
value
} else {
continue;
};
let refs = refs.clone();
let request_key = RequestKey::new(request.clone());
if value.as_bool() == Some(false) {
return Ok(Some(
ResolveResult::primary_with_affecting_sources(
request_key,
ResolveResultItem::Ignore,
refs,
)
.cell(),
));
}
if let Some(value) = value.as_str() {
if value == &*request {
// This would be a cycle, so we ignore it
return Ok(None);
}
return Ok(Some(
resolve_internal(
package_path,
Request::parse(Value::new(Pattern::Constant(value.into())))
.with_query(query)
.with_fragment(fragment),
options,
)
.with_replaced_request_key(value.into(), Value::new(request_key))
.with_affecting_sources(refs.into_iter().map(|src| *src).collect()),
));
}
ResolvingIssue {
severity: error_severity(options).await?,
file_path: *package_json_path,
request_type: format!("alias field ({field})"),
request: Request::parse(Value::new(Pattern::Constant(request)))
.to_resolved()
.await?,
resolve_options: options.to_resolved().await?,
error_message: Some(format!("invalid alias field value: {}", value)),
source: None,
}
.cell()
.emit();
return Ok(Some(
ResolveResult::unresolvable_with_affecting_sources(refs).cell(),
));
}

Check notice on line 2343 in turbopack/crates/turbopack-core/src/resolve/mod.rs

GitHub Actions / ast-grep lint

to-resolved-in-loop

Calling `Request::parse(Value::new(Pattern::Constant(request)))
Ok(None)
}
#[turbo_tasks::function]
async fn references(&self) -> Result<Vc<OutputAssets>> {
let mut references = Vec::new();
for &module in referenced_modules_and_affecting_sources(*self.source)
.await?
.iter()
{
references.push(ResolvedVc::upcast(
RebasedAsset::new(*module, *self.input_dir, *self.output_dir)
.to_resolved()
.await?,
));
}

Check notice on line 64 in turbopack/crates/turbopack-core/src/rebase.rs

GitHub Actions / ast-grep lint

to-resolved-in-loop

Calling `RebasedAsset::new(*module, *self.input_dir, *self.output_dir)
Ok(Vc::cell(references))
}
}
// The included chunk items and the availability info describe the chunk
// uniquely
let chunk_item_key = chunk_item_key();
for &chunk_item in chunk_items.iter() {
if let Some((common_path_vc, common_path_ref)) = common_path.as_mut() {
let path = chunk_item.asset_ident().path().await?;
while !path.is_inside_or_equal_ref(common_path_ref) {
let parent = common_path_vc.parent().to_resolved().await?;
if parent == *common_path_vc {
common_path = None;
break;
}
*common_path_vc = parent;
*common_path_ref = (*common_path_vc).await?;
}
}
assets.push((
chunk_item_key.to_resolved().await?,
chunk_item.content_ident().to_resolved().await?,
));
}

Check notice on line 287 in turbopack/crates/turbopack-css/src/chunk/mod.rs

GitHub Actions / ast-grep lint

to-resolved-in-loop

Calling `chunk_item_key.to_resolved().await?` in a loop could be a doing a lot of work sequentially. Consider producing an iterator of futures and using `try_join`.
let ident = AssetIdent {
path: if let Some((common_path, _)) = common_path {
let this = self.await?;
let content = this.content.await?;
let mut references = content.referenced_output_assets.await?.clone_value();
for item in content.chunk_items.iter() {
references.push(ResolvedVc::upcast(
SingleItemCssChunk::new(*this.chunking_context, **item)
.to_resolved()
.await?,
));
}

Check notice on line 320 in turbopack/crates/turbopack-css/src/chunk/mod.rs

GitHub Actions / ast-grep lint

to-resolved-in-loop

Calling `SingleItemCssChunk::new(*this.chunking_context, **item)
if *this
.chunking_context
.reference_chunk_source_maps(Vc::upcast(self))
};
let mut converted_entries = AutoMap::new();
for e in dir.entries() {
let entry_name: RcStr = e
.path()
.file_name()
.unwrap_or_default()
.to_string_lossy()
.into();
let entry_path = path.join(entry_name.clone()).to_resolved().await?;
converted_entries.insert(
entry_name,
match e {
DirEntry::Dir(_) => DirectoryEntry::Directory(entry_path),
DirEntry::File(_) => DirectoryEntry::File(entry_path),
},
);
}

Check notice on line 68 in turbopack/crates/turbo-tasks-fs/src/embed/fs.rs

GitHub Actions / ast-grep lint

to-resolved-in-loop

Calling `path.join(entry_name.clone()).to_resolved().await?` in a loop could be a doing a lot of work sequentially. Consider producing an iterator of futures and using `try_join`.
Ok(DirectoryContent::new(converted_entries))
}
// The included chunk items describe the chunk uniquely
let chunk_item_key = chunk_item_key();
for &(chunk_item, _) in chunk_items.iter() {
if let Some((common_path_vc, common_path_ref)) = common_path.as_mut() {
let path = chunk_item.asset_ident().path().await?;
while !path.is_inside_or_equal_ref(common_path_ref) {
let parent = common_path_vc.parent().to_resolved().await?;
if parent == *common_path_vc {
common_path = None;
break;
}
*common_path_vc = parent;
*common_path_ref = (*common_path_vc).await?;
}
}
assets.push((
chunk_item_key.to_resolved().await?,
chunk_item.content_ident().to_resolved().await?,
));
}

Check notice on line 107 in turbopack/crates/turbopack-ecmascript/src/chunk/mod.rs

GitHub Actions / ast-grep lint

to-resolved-in-loop

Calling `chunk_item_key.to_resolved().await?` in a loop could be a doing a lot of work sequentially. Consider producing an iterator of futures and using `try_join`.
// The previous resolve loop is no longer needed since we're already using ResolvedVc
let mut evaluation_references = Vec::new();
for (i, r) in eval_context.imports.references().enumerate() {
let r = EsmAssetReference::new(
*origin,
Request::parse(Value::new(RcStr::from(&*r.module_path).into())),
r.issue_source
.unwrap_or_else(|| IssueSource::from_source_only(*source)),
Value::new(r.annotations.clone()),
match options.tree_shaking_mode {
Some(TreeShakingMode::ModuleFragments) => match &r.imported_symbol {
ImportedSymbol::ModuleEvaluation => {
evaluation_references.push(i);
Some(ModulePart::evaluation())
}
ImportedSymbol::Symbol(name) => Some(ModulePart::export((&**name).into())),
ImportedSymbol::PartEvaluation(part_id) => {
evaluation_references.push(i);
Some(ModulePart::internal_evaluation(*part_id))
}
ImportedSymbol::Part(part_id) => Some(ModulePart::internal(*part_id)),
ImportedSymbol::Exports => Some(ModulePart::exports()),
},
Some(TreeShakingMode::ReexportsOnly) => match &r.imported_symbol {
ImportedSymbol::ModuleEvaluation => {
evaluation_references.push(i);
Some(ModulePart::evaluation())
}
ImportedSymbol::Symbol(name) => Some(ModulePart::export((&**name).into())),
ImportedSymbol::PartEvaluation(_) | ImportedSymbol::Part(_) => {
bail!("Internal imports doesn't exist in reexports only mode")
}
ImportedSymbol::Exports => None,
},
None => {
evaluation_references.push(i);
None
}
},
import_externals,
)
.to_resolved()
.await?;
import_references.push(r);
}

Check notice on line 659 in turbopack/crates/turbopack-ecmascript/src/references/mod.rs

GitHub Actions / ast-grep lint

to-resolved-in-loop

Calling `EsmAssetReference::new(
for i in evaluation_references {
let reference = import_references[i];