mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
docs(turbopack): Fix all warnings in cargo doc --no-deps --workspace, and run rustdoc as part of our CI checks (#91339)
This gets `cargo doc` clean, and enables it in CI so that we won't regress it (I'm open to removing this if it proves to be annoying). I also cleaned up some documentation and even found some dead code (deleted `turbopack/crates/turbopack-dev-server/src/source/conditional.rs`).
This commit is contained in:
@@ -98,6 +98,12 @@ pub fn root_task_dispose(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// [Peeks] at the [`Issue`] held by the given source and returns it as a [`PlainDiagnostic`].
|
||||
/// It does not [consume] any [`Issue`]s held by the source.
|
||||
///
|
||||
/// [Peeks]: turbo_tasks::CollectiblesSource::peek_collectibles
|
||||
/// [`Issue`]: turbopack_core::issue::Issue
|
||||
/// [consume]: turbo_tasks::CollectiblesSource::take_collectibles
|
||||
pub async fn get_issues<T: Send>(
|
||||
source: OperationVc<T>,
|
||||
filter: Vc<IssueFilter>,
|
||||
@@ -107,10 +113,11 @@ pub async fn get_issues<T: Send>(
|
||||
))
|
||||
}
|
||||
|
||||
/// Reads the [turbopack_core::diagnostics::Diagnostic] held
|
||||
/// by the given source and returns it as a
|
||||
/// [turbopack_core::diagnostics::PlainDiagnostic]. It does
|
||||
/// not consume any Diagnostics held by the source.
|
||||
/// [Peeks] at the [`Diagnostic`]s held by the given source and returns it as a [`PlainDiagnostic`].
|
||||
/// It does not [consume] any [`Diagnostic`]s held by the source.
|
||||
///
|
||||
/// [Peeks]: turbo_tasks::CollectiblesSource::peek_collectibles
|
||||
/// [consume]: turbo_tasks::CollectiblesSource::take_collectibles
|
||||
pub async fn get_diagnostics<T: Send>(
|
||||
source: OperationVc<T>,
|
||||
) -> Result<Arc<Vec<ReadRef<PlainDiagnostic>>>> {
|
||||
|
||||
@@ -70,10 +70,13 @@ pub const NODE_EXTERNALS: [&str; 68] = [
|
||||
"zlib",
|
||||
];
|
||||
|
||||
/// List of node.js internals that are supported by edge runtime.
|
||||
/// If anything Node.js builtin module apart from these these imports are
|
||||
/// used and user does not provide alias for the polyfill, a runtime error will be thrown.
|
||||
/// See https://vercel.com/docs/functions/runtimes/edge-runtime#compatible-node.js-modules
|
||||
/// The Node.js built-in modules that are supported by edge runtime.
|
||||
///
|
||||
/// If any Node.js builtin module apart from these these imports are used and the user does not
|
||||
/// provide an alias for it (i.e. a polyfill), a runtime error will be thrown.
|
||||
///
|
||||
/// See <https://vercel.com/docs/functions/runtimes/edge-runtime#compatible-node.js-modules>
|
||||
//
|
||||
// SAFETY: This has to be sorted alphabetically since we are doing binary search on it
|
||||
pub const EDGE_NODE_EXTERNALS: [&str; 7] = [
|
||||
"assert",
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
"build-native-wasi": "npx --package=@napi-rs/[email protected] napi build --platform --target wasm32-wasip1-threads -p next-napi-bindings --cwd ../../ --output-dir packages/next-swc/native --no-default-features",
|
||||
"build-wasm": "wasm-pack build ../../crates/wasm --scope=next",
|
||||
"cache-build-native": "[ -d native ] && echo $(ls native)",
|
||||
"rust-check-fmt": "cd ../..; cargo fmt -- --check",
|
||||
"rust-check-clippy": "cargo clippy --workspace --all-targets -- -D warnings -A deprecated",
|
||||
"rust-check-doc": "RUSTDOCFLAGS='-Zunstable-options --output-format=json' cargo doc --no-deps --workspace",
|
||||
"rust-check-fmt": "cd ../..; cargo fmt -- --check",
|
||||
"rust-check-napi": "cargo check -p next-napi-bindings",
|
||||
"test-cargo-unit": "cargo nextest run --workspace --exclude next-napi-bindings --exclude turbo-tasks-macros --cargo-profile release-with-assertions-no-lto --no-fail-fast"
|
||||
},
|
||||
|
||||
@@ -136,7 +136,34 @@
|
||||
"outputs": ["native/*.node", "native/index.d.ts"],
|
||||
},
|
||||
"rust-check": {
|
||||
"dependsOn": ["rust-check-fmt", "rust-check-clippy", "rust-check-napi"],
|
||||
"dependsOn": [
|
||||
"rust-check-clippy",
|
||||
"rust-check-doc",
|
||||
"rust-check-fmt",
|
||||
"rust-check-napi",
|
||||
],
|
||||
},
|
||||
"rust-check-clippy": {
|
||||
"inputs": [
|
||||
"../../.cargo/**",
|
||||
"../../crates/**",
|
||||
"../../turbopack/crates/**",
|
||||
"../../**/Cargo.toml",
|
||||
"../../**/Cargo.lock",
|
||||
"../../.github/workflows/build_and_deploy.yml",
|
||||
"../../rust-toolchain.toml",
|
||||
],
|
||||
},
|
||||
"rust-check-doc": {
|
||||
"inputs": [
|
||||
"../../.cargo/**",
|
||||
"../../crates/**",
|
||||
"../../turbopack/crates/**",
|
||||
"../../**/Cargo.toml",
|
||||
"../../**/Cargo.lock",
|
||||
"../../.github/workflows/build_and_deploy.yml",
|
||||
"../../rust-toolchain.toml",
|
||||
],
|
||||
},
|
||||
"rust-check-fmt": {
|
||||
"inputs": [
|
||||
@@ -150,17 +177,6 @@
|
||||
],
|
||||
"cache": false,
|
||||
},
|
||||
"rust-check-clippy": {
|
||||
"inputs": [
|
||||
"../../.cargo/**",
|
||||
"../../crates/**",
|
||||
"../../turbopack/crates/**",
|
||||
"../../**/Cargo.toml",
|
||||
"../../**/Cargo.lock",
|
||||
"../../.github/workflows/build_and_deploy.yml",
|
||||
"../../rust-toolchain.toml",
|
||||
],
|
||||
},
|
||||
"rust-check-napi": {
|
||||
"inputs": [
|
||||
"../../.cargo/**",
|
||||
|
||||
@@ -37,13 +37,12 @@ pub trait BackingStorage: BackingStorageSealed {
|
||||
///
|
||||
/// This typically means that we'll restart the process or `turbo-tasks` soon with a fresh
|
||||
/// database. If this happens, there's no point in writing anything else to disk, or flushing
|
||||
/// during [`KeyValueDatabase::shutdown`].
|
||||
/// during [`TurboTasksBackend::stop`].
|
||||
///
|
||||
/// This can be implemented by calling [`invalidate_db`] with
|
||||
/// the database's non-versioned base path.
|
||||
///
|
||||
/// [`KeyValueDatabase::shutdown`]: crate::database::key_value_database::KeyValueDatabase::shutdown
|
||||
/// [`invalidate_db`]: crate::database::db_invalidation::invalidate_db
|
||||
/// [`TurboTasksBackend::stop`]: turbo_tasks::backend::Backend::stop
|
||||
//
|
||||
// This can be implemented by calling `database::db_invalidation::invalidate_db` with the
|
||||
// database's non-versioned base path.
|
||||
fn invalidate(&self, reason_code: &str) -> Result<()>;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,9 +48,10 @@ impl Deref for Bytes {
|
||||
}
|
||||
}
|
||||
|
||||
/// Types that implement From<X> for Bytes {}
|
||||
/// Unfortunately, we cannot just use the more generic `Into<Bytes>` without
|
||||
/// running afoul of the `From<X> for X` base case, causing conflicting impls.
|
||||
/// Types that `impl From<CustomType> for Bytes {}`
|
||||
///
|
||||
/// Unfortunately, we cannot just use the more generic `Into<Bytes>` without running afoul of the
|
||||
/// `From<X> for X` base case, causing conflicting impls.
|
||||
pub trait IntoBytes: Into<CBytes> {}
|
||||
impl IntoBytes for &'static [u8] {}
|
||||
impl IntoBytes for &'static str {}
|
||||
|
||||
@@ -25,17 +25,17 @@ pub fn directory_from_include_dir(
|
||||
Vc::upcast(EmbeddedFileSystem::new(name, dir))
|
||||
}
|
||||
|
||||
/// Returns an embedded [Vc<Box<dyn FileSystem>>] for the given path.
|
||||
/// Returns an embedded [`Vc<Box<dyn FileSystem>>`][FileSystem] for the given path.
|
||||
///
|
||||
/// This will embed a directory's content into the binary and
|
||||
/// create an [Vc<EmbeddedFileSystem>].
|
||||
/// This will embed a directory's content into the binary and create an
|
||||
/// [`Vc<EmbeddedFileSystem>`][EmbeddedFileSystem].
|
||||
///
|
||||
/// If you enable the `dynamic_embed_contents` feature, calling
|
||||
/// the macro will return a [Vc<DiskFileSystem>].
|
||||
/// If you enable the `dynamic_embed_contents` feature, calling the macro will return a
|
||||
/// [`Vc<DiskFileSystem>`][DiskFileSystem].
|
||||
///
|
||||
/// This enables dynamic linking (and hot reloading) of embedded files/dirs.
|
||||
/// A binary built with `dynamic_embed_contents` enabled is **is not portable**,
|
||||
/// only the directory path will be embedded into the binary.
|
||||
/// This enables dynamic linking (and hot reloading) of embedded files/dirs. A binary built with
|
||||
/// `dynamic_embed_contents` enabled is **is not portable**, only the directory path will be
|
||||
/// embedded into the binary.
|
||||
#[macro_export]
|
||||
macro_rules! embed_directory {
|
||||
($name:tt, $path:tt) => {{ // make sure the path contains `$CARGO_MANIFEST_DIR`
|
||||
|
||||
@@ -91,19 +91,6 @@ use crate::{
|
||||
};
|
||||
pub use crate::{read_glob::ReadGlobResult, virtual_fs::VirtualFileSystem};
|
||||
|
||||
/// A (somewhat arbitrary) filename limit that we should try to keep output file names below.
|
||||
///
|
||||
/// For the sake of consistency, this is a fixed constant that is likely to be safe across all
|
||||
/// platforms.
|
||||
///
|
||||
/// Different operating systems have different limits on file name and file path. See
|
||||
/// [`validate_path_length`] for details. Because this only accounts for a single path segment, and
|
||||
/// not the total path length, this cannot not guarantee a full file path is safe.
|
||||
///
|
||||
/// To ensure file names are kept within this limit, call
|
||||
/// [`FileSystemPath::truncate_file_name_with_hash`].
|
||||
pub const MAX_SAFE_FILE_NAME_LENGTH: usize = 200;
|
||||
|
||||
/// Validate the path, returning the valid path, a modified-but-now-valid path, or bailing with an
|
||||
/// error.
|
||||
///
|
||||
@@ -1553,9 +1540,8 @@ impl FileSystemPath {
|
||||
FileSystemPath { fs, path }
|
||||
}
|
||||
|
||||
/// Adds a subpath to the current path. The /-separate path argument might
|
||||
/// contain ".." or "." segments, but it must not leave the root of the
|
||||
/// filesystem.
|
||||
/// Adds a subpath to the current path. The /-separated `path` argument might contain ".." or
|
||||
/// "." segments, but it must not leave the root of the filesystem.
|
||||
pub fn join(&self, path: &str) -> Result<Self> {
|
||||
if let Some(path) = join_path(&self.path, path) {
|
||||
Ok(Self::new_normalized(self.fs, path.into()))
|
||||
@@ -1568,7 +1554,7 @@ impl FileSystemPath {
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a suffix to the filename. [path] must not contain `/`.
|
||||
/// Adds a suffix to the filename. `path` must not contain `/`.
|
||||
pub fn append(&self, path: &str) -> Result<Self> {
|
||||
if path.contains('/') {
|
||||
bail!(
|
||||
@@ -1583,12 +1569,12 @@ impl FileSystemPath {
|
||||
))
|
||||
}
|
||||
|
||||
/// Adds a suffix to the basename of the filename. [appending] must not
|
||||
/// contain `/`. Extension will stay intact.
|
||||
/// Adds a suffix to the basename of the file path. `appending` must not contain `/`. The [file
|
||||
/// extension][FileSystemPath::extension] will stay intact.
|
||||
pub fn append_to_stem(&self, appending: &str) -> Result<Self> {
|
||||
if appending.contains('/') {
|
||||
bail!(
|
||||
"FileSystemPath(\"{}\").append_to_stem(\"{}\") must not append '/'",
|
||||
"FileSystemPath({:?}).append_to_stem({:?}) must not append '/'",
|
||||
self.path,
|
||||
appending,
|
||||
)
|
||||
@@ -1628,14 +1614,15 @@ impl FileSystemPath {
|
||||
None
|
||||
}
|
||||
|
||||
/// DETERMINISM: Result is in random order. Either sort result or do not depend
|
||||
/// on the order.
|
||||
/// DETERMINISM: Result is in random order. Either sort the result or do not depend on the
|
||||
/// order.
|
||||
pub fn read_glob(&self, glob: Vc<Glob>) -> Vc<ReadGlobResult> {
|
||||
read_glob(self.clone(), glob)
|
||||
}
|
||||
|
||||
// Tracks all files and directories matching the glob
|
||||
// Follows symlinks as though they were part of the original hierarchy.
|
||||
// Tracks all files and directories matching the glob using the filesystem watcher. Follows
|
||||
// symlinks as though they were part of the original hierarchy. The returned [`Vc`] will be
|
||||
// invalidated if a file or directory changes.
|
||||
pub fn track_glob(&self, glob: Vc<Glob>, include_dot_files: bool) -> Vc<Completion> {
|
||||
track_glob(self.clone(), glob, include_dot_files)
|
||||
}
|
||||
@@ -2046,7 +2033,7 @@ pub enum LinkContent {
|
||||
///
|
||||
/// We don't use the [`FileSystemPath`] to store the target, because the [`FileSystemPath`] is
|
||||
/// always normalized. In [`FileSystemPath::write_symbolic_link_dir`] we need to compare
|
||||
/// `target` with the value returned by [`sys::fs::read_link`].
|
||||
/// `target` with the value returned by [`std::fs::read_link`].
|
||||
Link {
|
||||
target: RcStr,
|
||||
link_type: LinkType,
|
||||
|
||||
@@ -159,8 +159,8 @@ impl<T: Into<Bytes>> From<T> for Rope {
|
||||
impl RopeBuilder {
|
||||
/// Push owned bytes into the Rope.
|
||||
///
|
||||
/// If possible use [push_static_bytes] or `+=` operation instead, as they
|
||||
/// will create a reference to shared memory instead of cloning the bytes.
|
||||
/// If possible, use [`RopeBuilder::push_static_bytes`] or `+=` operation instead. That will
|
||||
/// create a reference to shared memory instead of cloning the bytes.
|
||||
pub fn push_bytes(&mut self, bytes: &[u8]) {
|
||||
if bytes.is_empty() {
|
||||
return;
|
||||
@@ -414,7 +414,7 @@ impl DeterministicHash for RopeBytesOnlyHash<'_> {
|
||||
/// [`Rope::to_bytes`] instead would be easier, but would require copying to an intermediate buffer.
|
||||
///
|
||||
/// This len + bytes format is similar to how bincode would normally encode a `&[u8]`:
|
||||
/// https://docs.rs/bincode/latest/bincode/spec/index.html#collections
|
||||
/// <https://docs.rs/bincode/latest/bincode/spec/index.html#collections>
|
||||
impl Encode for Rope {
|
||||
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
|
||||
self.length.encode(encoder)?;
|
||||
@@ -882,7 +882,7 @@ impl BufRead for RopeReader<'_> {
|
||||
}
|
||||
|
||||
impl<'a> Stream for RopeReader<'a> {
|
||||
/// This is efficiently streamable into a [`Hyper::Body`] if each item is cloned into an owned
|
||||
/// This is efficiently streamable into a `Hyper::Body` if each item is cloned into an owned
|
||||
/// `Bytes` instance.
|
||||
type Item = Result<&'a Bytes>;
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ use turbo_tasks::ResolvedVc;
|
||||
|
||||
use crate::{DiskFileSystem, FileSystemPath};
|
||||
|
||||
/// Converts a disk access Result<T> into a Result<Some<T>>, where a NotFound
|
||||
/// error results in a None value. This is purely to reduce boilerplate code
|
||||
/// comparing NotFound errors against all other errors.
|
||||
/// Converts a disk access `Result<T>` into a `Result<Some<T>>`, where a [`ErrorKind::NotFound`] (or
|
||||
/// [`ErrorKind::InvalidFilename`]) error results in a [`None`] value. This is purely to reduce
|
||||
/// boilerplate code comparing [`ErrorKind::NotFound`] errors against all other errors.
|
||||
pub fn extract_disk_access<T>(value: io::Result<T>, path: &Path) -> Result<Option<T>> {
|
||||
match value {
|
||||
Ok(v) => Ok(Some(v)),
|
||||
|
||||
@@ -24,11 +24,17 @@ pub enum HashAlgorithm {
|
||||
Xxh3Hash64Base40,
|
||||
/// xxh3 128-bit hash encoded as a 25-character base40 string (0-9 a-z _ - ~ .)
|
||||
Xxh3Hash128Base40,
|
||||
/// Used for https://nextjs.org/docs/app/guides/content-security-policy#enabling-sri
|
||||
/// Used for [Subresource Integrity (SRI)][sri].
|
||||
///
|
||||
/// [sri]: https://nextjs.org/docs/app/guides/content-security-policy#enabling-sri
|
||||
Sha256Base64,
|
||||
/// Used for https://nextjs.org/docs/app/guides/content-security-policy#enabling-sri
|
||||
/// Used for [Subresource Integrity (SRI)][sri].
|
||||
///
|
||||
/// [sri]: https://nextjs.org/docs/app/guides/content-security-policy#enabling-sri
|
||||
Sha384Base64,
|
||||
/// Used for https://nextjs.org/docs/app/guides/content-security-policy#enabling-sri
|
||||
/// Used for [Subresource Integrity (SRI)][sri].
|
||||
///
|
||||
/// [sri]: https://nextjs.org/docs/app/guides/content-security-policy#enabling-sri
|
||||
Sha512Base64,
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ The `#[turbo_tasks::function]` macro **rewrites the arguments and return values*
|
||||
- Method arguments of **`&self`** are **rewritten to `self: Vc<Self>`**.
|
||||
|
||||
[`ResolvedVc<T>`]: crate::ResolvedVc
|
||||
[`FromTaskInput`]: crate::FromTaskInput
|
||||
[`FromTaskInput`]: crate::task::FromTaskInput
|
||||
|
||||
### Return Type Rewrite Rules
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
//!
|
||||
//! This avoid the problem of sleeping threads with mimalloc when using rayon in combination with
|
||||
//! tokio. It also avoid having multiple thread pools.
|
||||
//! see also https://pwy.io/posts/mimalloc-cigarette/
|
||||
//!
|
||||
//! See also: <https://pwy.io/posts/mimalloc-cigarette/>
|
||||
|
||||
use crate::{
|
||||
scope::scope_and_block,
|
||||
|
||||
@@ -155,10 +155,10 @@ pub struct Scope<'scope, 'env: 'scope, R: Send + 'env> {
|
||||
handle: Handle,
|
||||
turbo_tasks: Option<Arc<dyn TurboTasksApi>>,
|
||||
span: Span,
|
||||
/// Invariance over 'env, to make sure 'env cannot shrink,
|
||||
/// which is necessary for soundness.
|
||||
/// Invariance over 'env, to make sure 'env cannot shrink, which is necessary for soundness.
|
||||
///
|
||||
/// see https://doc.rust-lang.org/src/std/thread/scoped.rs.html#12-29
|
||||
/// See the comment in the stdlib implementation:
|
||||
/// <https://github.com/rust-lang/rust/blob/3b1b0ef4d8/library/std/src/thread/scoped.rs#L12-L33>
|
||||
env: PhantomData<&'env mut &'env ()>,
|
||||
}
|
||||
|
||||
|
||||
@@ -8,20 +8,26 @@ use turbo_tasks_hash::{HashAlgorithm, Xxh3Hash64Hasher};
|
||||
|
||||
use crate::version::{VersionedAssetContent, VersionedContent};
|
||||
|
||||
/// An asset. It also forms a graph when following [Asset::references].
|
||||
/// A file or intermediate result containing content as a [`Rope`] or a symlink.
|
||||
///
|
||||
/// This is a supertrait for [`Source`], [`OutputAsset`], and [`OutputChunk`].
|
||||
///
|
||||
/// [`Rope`]: turbo_tasks_fs::rope::Rope
|
||||
/// [`Source`]: crate::source::Source
|
||||
/// [`OutputAsset`]: crate::output::OutputAsset
|
||||
/// [`OutputChunk`]: crate::chunk::OutputChunk
|
||||
#[turbo_tasks::value_trait]
|
||||
pub trait Asset {
|
||||
/// The content of the [Asset].
|
||||
#[turbo_tasks::function]
|
||||
fn content(self: Vc<Self>) -> Vc<AssetContent>;
|
||||
|
||||
/// The content of the [Asset] alongside its version.
|
||||
/// The content of the `Asset` alongside its version.
|
||||
#[turbo_tasks::function]
|
||||
fn versioned_content(self: Vc<Self>) -> Result<Vc<Box<dyn VersionedContent>>> {
|
||||
Ok(Vc::upcast(VersionedAssetContent::new(self.content())))
|
||||
}
|
||||
|
||||
/// Hash of the content of the [Asset]
|
||||
/// Hash of the content of the `Asset`.
|
||||
#[turbo_tasks::function]
|
||||
fn content_hash(self: Vc<Self>, algorithm: HashAlgorithm) -> Vc<Option<RcStr>> {
|
||||
self.content().content_hash(algorithm)
|
||||
|
||||
@@ -202,25 +202,25 @@ pub struct Chunks(Vec<ResolvedVc<Box<dyn Chunk>>>);
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Chunks {
|
||||
/// Creates a new empty [Vc<Chunks>].
|
||||
#[turbo_tasks::function]
|
||||
pub fn empty() -> Vc<Self> {
|
||||
Vc::cell(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
/// A [Chunk] group chunk items together into something that will become an [OutputAsset].
|
||||
/// It usually contains multiple chunk items.
|
||||
// TODO This could be simplified to and merged with [OutputChunk]
|
||||
/// Groups chunk items together into something that will become an [`OutputAsset`]. It usually
|
||||
/// contains multiple chunk items.
|
||||
///
|
||||
/// [`OutputAsset`]: crate::output::OutputAsset
|
||||
//
|
||||
// TODO: This could be simplified to and merged with OutputChunk
|
||||
#[turbo_tasks::value_trait]
|
||||
pub trait Chunk: OutputAssetsReference {
|
||||
#[turbo_tasks::function]
|
||||
fn ident(self: Vc<Self>) -> Vc<AssetIdent>;
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn chunking_context(self: Vc<Self>) -> Vc<Box<dyn ChunkingContext>>;
|
||||
// fn path(self: Vc<Self>) -> Vc<FileSystemPath> {
|
||||
// self.ident().path()
|
||||
// }
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn chunk_items(self: Vc<Self>) -> Vc<ChunkItems> {
|
||||
|
||||
@@ -49,16 +49,13 @@ pub struct DiagnosticPayload(
|
||||
#[bincode(with = "turbo_bincode::indexmap")] pub FxIndexMap<RcStr, RcStr>,
|
||||
);
|
||||
|
||||
/// An arbitrary payload can be used to analyze, diagnose
|
||||
/// Turbopack's behavior.
|
||||
/// An arbitrary payload can be used to analyze, diagnose Turbopack's behavior.
|
||||
#[turbo_tasks::value_trait]
|
||||
pub trait Diagnostic {
|
||||
/// [NOTE]: Pseudo-reserved; this is not being used currently.
|
||||
/// The `type` of the diagnostics that can be used selectively filtered by
|
||||
/// consumers. For example, this could be `telemetry`, or
|
||||
/// `slow_perf_event`, or something else. This is not strongly typed
|
||||
/// though; since consumer or implementation may need to define own
|
||||
/// category.
|
||||
/// **NOTE:** Pseudo-reserved; this is not being used currently. The `type` of the diagnostics
|
||||
/// that can be used selectively filtered by consumers. For example, this could be `telemetry`,
|
||||
/// or `slow_perf_event`, or something else. This is not strongly typed though; since consumer
|
||||
/// or implementation may need to define own category.
|
||||
#[turbo_tasks::function]
|
||||
fn category(&self) -> Vc<RcStr>;
|
||||
/// Name of the specific diagnostic event.
|
||||
@@ -113,8 +110,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of diagnostics captured with
|
||||
/// [`DiagnosticsVc::peek_diagnostics_with_path`] and
|
||||
/// A list of diagnostics captured with [`DiagnosticContextExt::peek_diagnostics`] and
|
||||
#[derive(Debug)]
|
||||
#[turbo_tasks::value]
|
||||
pub struct CapturedDiagnostics {
|
||||
|
||||
@@ -35,7 +35,7 @@ pub enum ChunkLoading {
|
||||
Edge,
|
||||
/// CommonJS in Node.js
|
||||
NodeJs,
|
||||
/// <script> and <link> tags in the browser
|
||||
/// `<script>` and `<link>` tags in the browser
|
||||
Dom,
|
||||
}
|
||||
|
||||
|
||||
@@ -405,8 +405,7 @@ impl IssueFilter {
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of issues captured with [`Issue::peek_issues_with_path`] and
|
||||
/// [`Issue::take_issues`].
|
||||
/// A list of issues captured with [`CollectibleIssuesExt::peek_issues`].
|
||||
#[turbo_tasks::value(shared)]
|
||||
#[derive(Debug)]
|
||||
pub struct CapturedIssues {
|
||||
@@ -414,26 +413,7 @@ pub struct CapturedIssues {
|
||||
tracer: ResolvedVc<DelegatingImportTracer>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl CapturedIssues {
|
||||
#[turbo_tasks::function]
|
||||
pub fn is_empty(&self) -> Vc<bool> {
|
||||
Vc::cell(self.is_empty_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl CapturedIssues {
|
||||
/// Returns true if there are no issues.
|
||||
pub fn is_empty_ref(&self) -> bool {
|
||||
self.issues.is_empty()
|
||||
}
|
||||
|
||||
/// Returns the number of issues.
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
pub fn len(&self) -> usize {
|
||||
self.issues.len()
|
||||
}
|
||||
|
||||
/// Returns an iterator over the issues.
|
||||
pub fn iter(&self) -> impl Iterator<Item = ResolvedVc<Box<dyn Issue>>> + '_ {
|
||||
self.issues.iter().copied()
|
||||
@@ -976,14 +956,13 @@ fn hash_plain_issue(issue: &PlainIssue, hasher: &mut Xxh3Hash64Hasher, full: boo
|
||||
}
|
||||
|
||||
impl PlainIssue {
|
||||
/// We need deduplicate issues that can come from unique paths, but
|
||||
/// represent the same underlying problem. Eg, a parse error for a file
|
||||
/// that is compiled in both client and server contexts.
|
||||
/// We need deduplicate issues that can come from unique paths, but represent the same
|
||||
/// underlying problem. E.g., a parse error for a file that is compiled in both client and
|
||||
/// server contexts.
|
||||
///
|
||||
/// Passing [full] will also hash any sub-issues and processing paths. While
|
||||
/// useful for generating exact matching hashes, it's possible for the
|
||||
/// same issue to pass from multiple processing paths, making for overly
|
||||
/// verbose logging.
|
||||
/// Passing `full` will also hash any sub-issues and processing paths. While useful for
|
||||
/// generating exact matching hashes, it's possible for the same issue to pass from multiple
|
||||
/// processing paths, making for overly verbose logging.
|
||||
pub fn internal_hash_ref(&self, full: bool) -> u64 {
|
||||
let mut hasher = Xxh3Hash64Hasher::new();
|
||||
hash_plain_issue(self, &mut hasher, full);
|
||||
|
||||
@@ -13,13 +13,15 @@ pub enum StyleType {
|
||||
#[derive(Hash, Debug, Copy, Clone)]
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub enum ModuleSideEffects {
|
||||
/// Analysis determined that the module evaluation is side effect free
|
||||
/// the module may still be side effectful based on its imports.
|
||||
/// Analysis determined that the module evaluation is free of side effects. The module may still
|
||||
/// have side effects based on its imports.
|
||||
///
|
||||
/// This module might not be chunked after Turbopack performed a global analysis on the module
|
||||
/// graph.
|
||||
ModuleEvaluationIsSideEffectFree,
|
||||
/// Is known to be side effect free either due to static analysis or some kind of configuration.
|
||||
/// Is known to be free of side effects either due to static analysis or some kind of
|
||||
/// configuration.
|
||||
///
|
||||
/// ```js
|
||||
/// "use turbopack no side effects"
|
||||
/// ```
|
||||
@@ -31,28 +33,30 @@ pub enum ModuleSideEffects {
|
||||
SideEffectful,
|
||||
}
|
||||
|
||||
/// A module. This usually represents parsed source code, which has references
|
||||
/// to other modules.
|
||||
/// A module. This usually represents parsed source code, which has references to other modules.
|
||||
#[turbo_tasks::value_trait]
|
||||
pub trait Module {
|
||||
/// The identifier of the [Module]. It's expected to be unique and capture
|
||||
/// all properties of the [Module].
|
||||
/// The identifier of the [`Module`]. It's expected to be unique and capture all properties of
|
||||
/// the [`Module`].
|
||||
#[turbo_tasks::function]
|
||||
fn ident(&self) -> Vc<AssetIdent>;
|
||||
|
||||
/// The identifier of the [Module] as string. It's expected to be unique and capture
|
||||
/// all properties of the [Module].
|
||||
/// The identifier of the [`Module`] as string. It's expected to be unique and capture all
|
||||
/// properties of the [`Module`].
|
||||
#[turbo_tasks::function]
|
||||
fn ident_string(self: Vc<Self>) -> Vc<RcStr> {
|
||||
self.ident().to_string()
|
||||
}
|
||||
|
||||
/// The source of the [Module].
|
||||
/// The source of the [`Module`].
|
||||
#[turbo_tasks::function]
|
||||
fn source(&self) -> Vc<OptionSource>;
|
||||
|
||||
/// Other [Module]s or [OutputAsset]s referenced from this [Module].
|
||||
// TODO refactor to avoid returning [OutputAsset]s here
|
||||
/// Other [`Module`]s or [`OutputAsset`]s referenced from this [`Module`].
|
||||
///
|
||||
/// [`OutputAsset`]: crate::output::OutputAsset
|
||||
//
|
||||
// TODO: refactor to avoid returning OutputAssets here
|
||||
#[turbo_tasks::function]
|
||||
fn references(self: Vc<Self>) -> Vc<ModuleReferences> {
|
||||
ModuleReferences::empty()
|
||||
@@ -64,7 +68,10 @@ pub trait Module {
|
||||
Vc::cell(false)
|
||||
}
|
||||
|
||||
/// Returns true if the module is marked as side effect free in package.json or by other means.
|
||||
/// Returns `true` if the module is marked as [free of side effects in
|
||||
/// `package.json`][packagejson] or by other means.
|
||||
///
|
||||
/// [packagejson]: https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free
|
||||
#[turbo_tasks::function]
|
||||
fn side_effects(self: Vc<Self>) -> Vc<ModuleSideEffects>;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ pub struct OptionOutputAsset(Option<ResolvedVc<Box<dyn OutputAsset>>>);
|
||||
|
||||
#[turbo_tasks::value_trait]
|
||||
pub trait OutputAssetsReference {
|
||||
/// References to other [OutputAsset]s from this [OutputAssetReference].
|
||||
/// References to other [`OutputAsset`]s from this [`OutputAssetsReference`].
|
||||
#[turbo_tasks::function]
|
||||
fn references(self: Vc<Self>) -> Vc<OutputAssetsWithReferenced> {
|
||||
OutputAssetsWithReferenced {
|
||||
|
||||
@@ -75,14 +75,13 @@ impl ModuleReference for SingleModuleReference {
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl SingleModuleReference {
|
||||
/// Create a new [Vc<SingleModuleReference>] that resolves to the given
|
||||
/// asset.
|
||||
/// Create a new instance that resolves to the given asset.
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(asset: ResolvedVc<Box<dyn Module>>, description: RcStr) -> Vc<Self> {
|
||||
Self::cell(SingleModuleReference { asset, description })
|
||||
}
|
||||
|
||||
/// The [Vc<Box<dyn Asset>>] that this reference resolves to.
|
||||
/// The [`Vc<Box<dyn Module>>`][Module] that this reference resolves to.
|
||||
#[turbo_tasks::function]
|
||||
pub fn asset(&self) -> Vc<Box<dyn Module>> {
|
||||
*self.asset
|
||||
@@ -155,14 +154,13 @@ impl ModuleReference for SingleOutputAssetReference {
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl SingleOutputAssetReference {
|
||||
/// Create a new [Vc<SingleOutputAssetReference>] that resolves to the given
|
||||
/// asset.
|
||||
/// Create a new `Vc<SingleOutputAssetReference>` that resolves to the given asset.
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(asset: ResolvedVc<Box<dyn OutputAsset>>, description: RcStr) -> Vc<Self> {
|
||||
Self::cell(SingleOutputAssetReference { asset, description })
|
||||
}
|
||||
|
||||
/// The [Vc<Box<dyn Asset>>] that this reference resolves to.
|
||||
/// The [`Vc<Box<dyn OutputAsset>>`][OutputAsset] that this reference resolves to.
|
||||
#[turbo_tasks::function]
|
||||
pub fn asset(&self) -> Vc<Box<dyn OutputAsset>> {
|
||||
*self.asset
|
||||
@@ -233,11 +231,10 @@ impl TracedModuleReference {
|
||||
}
|
||||
}
|
||||
|
||||
/// Aggregates all primary [Module]s referenced by an [Module]. [AssetReference]
|
||||
/// This does not include transitively references [Module]s, only includes
|
||||
/// primary [Module]s referenced.
|
||||
/// Aggregates all primary [`Module`]s referenced by an [`Module`]. This does not include
|
||||
/// transitively references [`Module`]s, only includes primary [`Module`]s referenced.
|
||||
///
|
||||
/// [Module]: crate::module::Module
|
||||
/// [`Module`]: crate::module::Module
|
||||
#[turbo_tasks::function]
|
||||
pub async fn primary_referenced_modules(module: Vc<Box<dyn Module>>) -> Result<Vc<Modules>> {
|
||||
let mut set = HashSet::new();
|
||||
|
||||
@@ -351,9 +351,9 @@ impl Display for ReferenceType {
|
||||
}
|
||||
|
||||
impl ReferenceType {
|
||||
/// Returns true if this reference type is internal. This will be used in
|
||||
/// combination with [`ModuleRuleCondition::Internal`] to determine if a
|
||||
/// rule should be applied to an internal asset/reference.
|
||||
/// Returns `true` if this reference type is internal. This is used by
|
||||
/// `turbopack::module_options::module_rule::ModuleRule::new_internal` to determine if a rule
|
||||
/// should be applied to an internal reference.
|
||||
pub fn is_internal(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
|
||||
@@ -17,7 +17,7 @@ use turbo_tasks::{
|
||||
|
||||
use crate::resolve::pattern::Pattern;
|
||||
|
||||
/// A map of [`AliasPattern`]s to the [`Template`]s they resolve to.
|
||||
/// A map of [`AliasPattern`]s as keys implemented using [`PatriciaMap`].
|
||||
///
|
||||
/// If a pattern has a wildcard character (*) within it, it will capture any
|
||||
/// number of characters, including path separators. The result of the capture
|
||||
@@ -578,7 +578,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// An alias pattern.
|
||||
/// An alias pattern commonly used for import paths. This should support [the functionality used in
|
||||
/// Typescript's tsconfig file][tsconfig].
|
||||
///
|
||||
/// [tsconfig]: https://www.typescriptlang.org/tsconfig/#paths
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
pub enum AliasPattern {
|
||||
/// Will match an exact string.
|
||||
|
||||
@@ -658,8 +658,8 @@ pub struct ResolveOptions {
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ResolveOptions {
|
||||
/// Returns a new [Vc<ResolveOptions>] with its import map extended to
|
||||
/// include the given import map.
|
||||
/// Returns a new `Vc<ResolveOptions>` with its import map extended to include the given import
|
||||
/// map.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn with_extended_import_map(
|
||||
self: Vc<Self>,
|
||||
@@ -677,8 +677,8 @@ impl ResolveOptions {
|
||||
Ok(resolve_options.cell())
|
||||
}
|
||||
|
||||
/// Returns a new [Vc<ResolveOptions>] with its fallback import map extended
|
||||
/// to include the given import map.
|
||||
/// Returns a new `Vc<ResolveOptions>` with its fallback import map extended to include the
|
||||
/// given import map.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn with_extended_fallback_import_map(
|
||||
self: Vc<Self>,
|
||||
|
||||
@@ -45,7 +45,9 @@ pub enum SubpathValue {
|
||||
/// allow remapping based on certain predefined conditions. Eg, if using
|
||||
/// ESM import syntax, the `import` condition allows you to remap to a
|
||||
/// file that uses ESM syntax.
|
||||
/// Node defines several conditions in https://nodejs.org/api/packages.html#conditional-exports
|
||||
///
|
||||
/// Node defines several conditions in
|
||||
/// <https://nodejs.org/api/packages.html#conditional-exports>
|
||||
/// TODO: Should this use an enum of predefined keys?
|
||||
Conditional(Vec<(RcStr, SubpathValue)>),
|
||||
|
||||
|
||||
@@ -3,8 +3,11 @@ use turbo_tasks::{ResolvedVc, Vc};
|
||||
|
||||
use crate::{asset::Asset, ident::AssetIdent};
|
||||
|
||||
/// (Unparsed) Source Code. Source Code is processed into [Module]s by the
|
||||
/// [AssetContext]. All [Source]s have content and an identifier.
|
||||
/// Unparsed input source code. Source code is processed into [`Module`]s by the [`AssetContext`].
|
||||
/// All `Source`s have content and an identifier.
|
||||
///
|
||||
/// [`Module`]: crate::module::Module
|
||||
/// [`AssetContext`]: crate::context::AssetContext
|
||||
#[turbo_tasks::value_trait]
|
||||
pub trait Source: Asset {
|
||||
/// The identifier of the [Source]. It's expected to be unique and capture
|
||||
|
||||
@@ -48,16 +48,8 @@ pub trait GenerateSourceMap {
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements the source map specification as either a decoded or sectioned sourcemap.
|
||||
///
|
||||
/// - A "decoded" map represents a source map as if it was came out of a JSON
|
||||
/// decode.
|
||||
/// - A "sectioned" source map is a tree of many [SourceMap]
|
||||
/// covering regions of an output file.
|
||||
///
|
||||
/// The distinction between the source map spec's [sourcemap::Index] and our
|
||||
/// [SourceMap::Sectioned] is whether the sections are represented with Vcs
|
||||
/// pointers.
|
||||
/// Implements the source map specification as a [decoded][`DecodedMap`] sourcemap. A "decoded" map
|
||||
/// represents a source map as if it was came out of a JSON decode.
|
||||
#[turbo_tasks::value(shared, cell = "new", eq = "manual")]
|
||||
#[derive(Debug)]
|
||||
pub struct SourceMap {
|
||||
@@ -236,12 +228,10 @@ impl TryInto<swc_sourcemap::RawToken> for Token {
|
||||
}
|
||||
|
||||
impl SourceMap {
|
||||
/// Creates a new SourceMap::Decoded Vc out of a [RegularMap] instance.
|
||||
fn new_regular(map: RegularMap) -> Self {
|
||||
Self::new_decoded(DecodedMap::Regular(map))
|
||||
}
|
||||
|
||||
/// Creates a new SourceMap::Decoded Vc out of a [DecodedMap] instance.
|
||||
fn new_decoded(map: DecodedMap) -> Self {
|
||||
SourceMap {
|
||||
map: Arc::new(CrateMapWrapper(map)),
|
||||
|
||||
@@ -52,7 +52,7 @@ impl SourcePos {
|
||||
/// Line terminators are the classic "\n", "\r", "\r\n" (which counts as
|
||||
/// a single terminator), and JSON LINE/PARAGRAPH SEPARATORs.
|
||||
///
|
||||
/// See https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#sec-line-terminators
|
||||
/// See <https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#sec-line-terminators>
|
||||
pub fn update(&mut self, code: &[u8]) {
|
||||
// JS source text is interpreted as UCS-2, which is basically UTF-16 with less
|
||||
// restrictions. We cannot iterate UTF-8 bytes here, 2-byte UTF-8 octets
|
||||
|
||||
@@ -13,10 +13,15 @@ use crate::asset::AssetContent;
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub struct OptionVersionedContent(Option<ResolvedVc<Box<dyn VersionedContent>>>);
|
||||
|
||||
/// The content of an [Asset] alongside its version.
|
||||
/// The content of an [`Asset`] alongside its version, returned by [`Asset::versioned_content`].
|
||||
///
|
||||
/// [`Asset`]: crate::asset::Asset
|
||||
/// [`Asset::versioned_content`]: crate::asset::Asset::versioned_content
|
||||
#[turbo_tasks::value_trait]
|
||||
pub trait VersionedContent {
|
||||
/// The content of the [Asset].
|
||||
/// The content of the [`Asset`].
|
||||
///
|
||||
/// [`Asset`]: crate::asset::Asset
|
||||
#[turbo_tasks::function]
|
||||
fn content(self: Vc<Self>) -> Vc<AssetContent>;
|
||||
|
||||
@@ -85,7 +90,7 @@ impl VersionedContent for VersionedAssetContent {
|
||||
#[turbo_tasks::value_impl]
|
||||
impl VersionedAssetContent {
|
||||
#[turbo_tasks::function]
|
||||
/// Creates a new [Vc<VersionedAssetContent>] from a [Vc<FileContent>].
|
||||
/// Creates a new instance from a [`Vc<AssetContent>`][AssetContent].
|
||||
pub async fn new(asset_content: Vc<AssetContent>) -> Result<Vc<Self>> {
|
||||
let asset_content = asset_content.await?;
|
||||
Ok(Self::cell(VersionedAssetContent { asset_content }))
|
||||
|
||||
@@ -48,9 +48,8 @@ pub enum EffectMode {
|
||||
None,
|
||||
/// As a direct `useEffect` hook in the component's body.
|
||||
Hook,
|
||||
/// Rendering an <Effect /> client-side component that has the `useEffect`
|
||||
/// hook instead. Good for testing React Server Components, as they can't
|
||||
/// use `useEffect` hooks directly.
|
||||
/// Rendering an `<Effect />` client-side component that has the `useEffect` hook instead. Good
|
||||
/// for testing React Server Components, as they can't use `useEffect` hooks directly.
|
||||
Component,
|
||||
}
|
||||
|
||||
|
||||
@@ -30,10 +30,12 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
/// A global CSS module. Notably not a `.module.css` module, which is [`EcmascriptCssModule`]
|
||||
/// instead.
|
||||
///
|
||||
/// [`EcmascriptCssModule`]: crate::EcmascriptCssModule
|
||||
#[turbo_tasks::value]
|
||||
#[derive(Clone)]
|
||||
/// A global CSS asset. Notably not a `.module.css` module, which is [`EcmascriptCssModule`]
|
||||
/// instead.
|
||||
pub struct CssModule {
|
||||
source: ResolvedVc<Box<dyn Source>>,
|
||||
asset_context: ResolvedVc<Box<dyn AssetContext>>,
|
||||
|
||||
@@ -36,9 +36,12 @@ use crate::{
|
||||
references::{compose::CssModuleComposeReference, internal::InternalCssAssetReference},
|
||||
};
|
||||
|
||||
/// A [CSS Module, as in `.module.css`][spec]. For a global CSS module, see [`CssModule`].
|
||||
///
|
||||
/// [spec]: https://github.com/css-modules/css-modules
|
||||
/// [`CssModule`]: crate::CssModule
|
||||
#[turbo_tasks::value]
|
||||
#[derive(Clone)]
|
||||
/// A CSS Module asset, as in `.module.css`. For a global CSS module, see [`CssModule`].
|
||||
pub struct EcmascriptCssModule {
|
||||
pub source: ResolvedVc<Box<dyn Source>>,
|
||||
pub asset_context: ResolvedVc<Box<dyn AssetContext>>,
|
||||
|
||||
@@ -8,10 +8,7 @@ use crate::source::{
|
||||
route_tree::{RouteTree, RouteTrees},
|
||||
};
|
||||
|
||||
/// Combines multiple [ContentSource]s by trying all content sources in order.
|
||||
///
|
||||
/// The content source which responds with the most specific response (that is
|
||||
/// not a [ContentSourceContent::NotFound]) will be returned.
|
||||
/// Combines multiple [`ContentSource`]s by [merging][RouteTrees::merge] [`RouteTree`]s.
|
||||
#[turbo_tasks::value(shared)]
|
||||
pub struct CombinedContentSource {
|
||||
pub sources: Vec<ResolvedVc<Box<dyn ContentSource>>>,
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
use anyhow::Result;
|
||||
use turbo_rcstr::{RcStr, rcstr};
|
||||
use turbo_tasks::{Completion, ResolvedVc, State, Vc};
|
||||
use turbopack_core::introspect::{Introspectable, IntrospectableChildren};
|
||||
|
||||
use crate::source::{
|
||||
ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataVary,
|
||||
ContentSourceSideEffect, ContentSources, GetContentSourceContent,
|
||||
route_tree::{MapGetContentSourceContent, RouteTree, RouteTrees},
|
||||
};
|
||||
|
||||
/// Combines two [ContentSource]s like the [CombinedContentSource], but only
|
||||
/// allows to serve from the second source when the first source has
|
||||
/// successfully served something once.
|
||||
///
|
||||
/// This is a laziness optimization when the content of the second source can
|
||||
/// only be reached via references from the first source.
|
||||
///
|
||||
/// For example, we use that in the content source that handles SSR rendering of
|
||||
/// pages. Here HTML and "other assets" are in different content sources. So we
|
||||
/// use this source to only serve (and process) "other assets" when the HTML was
|
||||
/// served once.
|
||||
#[turbo_tasks::value(serialization = "none", eq = "manual", cell = "new")]
|
||||
pub struct ConditionalContentSource {
|
||||
activator: ResolvedVc<Box<dyn ContentSource>>,
|
||||
action: ResolvedVc<Box<dyn ContentSource>>,
|
||||
activated: State<bool>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ConditionalContentSource {
|
||||
#[turbo_tasks::function]
|
||||
pub fn new(
|
||||
activator: ResolvedVc<Box<dyn ContentSource>>,
|
||||
action: ResolvedVc<Box<dyn ContentSource>>,
|
||||
) -> Vc<Self> {
|
||||
ConditionalContentSource {
|
||||
activator,
|
||||
action,
|
||||
activated: State::new(false),
|
||||
}
|
||||
.cell()
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ContentSource for ConditionalContentSource {
|
||||
#[turbo_tasks::function]
|
||||
async fn get_routes(self: ResolvedVc<Self>) -> Result<Vc<RouteTree>> {
|
||||
let this = self.await?;
|
||||
Ok(if !*this.activated.get() {
|
||||
this.activator.get_routes().map_routes(Vc::upcast(
|
||||
ConditionalContentSourceMapper { source: self }.cell(),
|
||||
))
|
||||
} else {
|
||||
Vc::<RouteTrees>::cell(vec![
|
||||
this.activator.get_routes().to_resolved().await?,
|
||||
this.action.get_routes().to_resolved().await?,
|
||||
])
|
||||
.merge()
|
||||
})
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn get_children(&self) -> Vc<ContentSources> {
|
||||
Vc::cell(vec![self.activator, self.action])
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value]
|
||||
struct ConditionalContentSourceMapper {
|
||||
source: ResolvedVc<ConditionalContentSource>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl MapGetContentSourceContent for ConditionalContentSourceMapper {
|
||||
#[turbo_tasks::function]
|
||||
fn map_get_content(
|
||||
&self,
|
||||
get_content: ResolvedVc<Box<dyn GetContentSourceContent>>,
|
||||
) -> Vc<Box<dyn GetContentSourceContent>> {
|
||||
Vc::upcast(
|
||||
ActivateOnGetContentSource {
|
||||
source: self.source,
|
||||
get_content,
|
||||
}
|
||||
.cell(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl Introspectable for ConditionalContentSource {
|
||||
#[turbo_tasks::function]
|
||||
fn ty(&self) -> Vc<RcStr> {
|
||||
Vc::cell(rcstr!("conditional content source"))
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn details(&self) -> Vc<RcStr> {
|
||||
Vc::cell(if *self.activated.get() {
|
||||
rcstr!("activated")
|
||||
} else {
|
||||
rcstr!("not activated")
|
||||
})
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn title(&self) -> Result<Vc<RcStr>> {
|
||||
if let Some(activator) = ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.activator)
|
||||
{
|
||||
Ok(activator.title())
|
||||
} else {
|
||||
Ok(Vc::<RcStr>::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
fn children(&self) -> Result<Vc<IntrospectableChildren>> {
|
||||
Ok(Vc::cell(
|
||||
[
|
||||
ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.activator)
|
||||
.map(|i| (rcstr!("activator"), i)),
|
||||
ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.action)
|
||||
.map(|i| (rcstr!("action"), i)),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(serialization = "none", eq = "manual", cell = "new")]
|
||||
struct ActivateOnGetContentSource {
|
||||
source: ResolvedVc<ConditionalContentSource>,
|
||||
get_content: ResolvedVc<Box<dyn GetContentSourceContent>>,
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl GetContentSourceContent for ActivateOnGetContentSource {
|
||||
#[turbo_tasks::function]
|
||||
fn vary(&self) -> Vc<ContentSourceDataVary> {
|
||||
self.get_content.vary()
|
||||
}
|
||||
|
||||
#[turbo_tasks::function]
|
||||
async fn get(
|
||||
self: ResolvedVc<Self>,
|
||||
path: RcStr,
|
||||
data: ContentSourceData,
|
||||
) -> Result<Vc<ContentSourceContent>> {
|
||||
turbo_tasks::emit(ResolvedVc::upcast::<Box<dyn ContentSourceSideEffect>>(self));
|
||||
Ok(self.await?.get_content.get(path, data))
|
||||
}
|
||||
}
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl ContentSourceSideEffect for ActivateOnGetContentSource {
|
||||
#[turbo_tasks::function]
|
||||
async fn apply(&self) -> Result<Vc<Completion>> {
|
||||
self.source.await?.activated.set(true);
|
||||
Ok(Completion::new())
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
pub mod asset_graph;
|
||||
pub mod combined;
|
||||
pub mod conditional;
|
||||
pub mod headers;
|
||||
pub mod issue_context;
|
||||
pub mod lazy_instantiated;
|
||||
pub mod query;
|
||||
pub mod request;
|
||||
pub(crate) mod resolve;
|
||||
pub mod resolve;
|
||||
pub mod route_tree;
|
||||
pub mod router;
|
||||
pub mod static_assets;
|
||||
@@ -62,17 +61,16 @@ impl Version for ProxyResult {
|
||||
}
|
||||
}
|
||||
|
||||
/// A functor to receive the actual content of a content source result.
|
||||
/// Receives the actual content for a [`ContentSource`].
|
||||
#[turbo_tasks::value_trait]
|
||||
pub trait GetContentSourceContent {
|
||||
/// Specifies data requirements for the get function. Restricting data
|
||||
/// passed allows to cache the get method.
|
||||
/// Specifies data requirements for the [`get`][Self::get] function. Restricting data passed
|
||||
/// allows improved caching of the [`get`][Self::get] method.
|
||||
#[turbo_tasks::function]
|
||||
fn vary(self: Vc<Self>) -> Vc<ContentSourceDataVary> {
|
||||
ContentSourceDataVary::default().cell()
|
||||
}
|
||||
|
||||
/// Get the content
|
||||
#[turbo_tasks::function]
|
||||
fn get(self: Vc<Self>, path: RcStr, data: ContentSourceData) -> Vc<ContentSourceContent>;
|
||||
}
|
||||
@@ -88,8 +86,8 @@ pub struct StaticContent {
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
// TODO add Dynamic variant in future to allow streaming and server responses
|
||||
/// The content of a result that is returned by a content source.
|
||||
/// The content of a result that is returned by [`GetContentSourceContent::get`].
|
||||
// TODO: add a `Dynamic` variant in future to allow streaming and server responses
|
||||
pub enum ContentSourceContent {
|
||||
NotFound,
|
||||
Static(ResolvedVc<StaticContent>),
|
||||
@@ -156,12 +154,10 @@ impl HeaderList {
|
||||
}
|
||||
}
|
||||
|
||||
/// Additional info passed to the ContentSource. It was extracted from the http
|
||||
/// request.
|
||||
/// Additional info passed to the [`ContentSource`]. It was extracted from the http request.
|
||||
///
|
||||
/// Note that you might not receive information that has not been requested via
|
||||
/// `ContentSource::vary()`. So make sure to request all information that's
|
||||
/// needed.
|
||||
/// [`GetContentSourceContent::vary`]. So make sure to request all information that's needed.
|
||||
#[derive(
|
||||
PartialEq,
|
||||
Eq,
|
||||
@@ -263,7 +259,8 @@ impl ContentSourceDataFilter {
|
||||
}
|
||||
|
||||
/// Merges the filtering to get a filter that covers both filters. Works on
|
||||
/// Option<DataFilter> where None is considers as empty filter.
|
||||
/// [`Option<ContentSourceDataFilter>`][ContentSourceDataFilter] where [`None`] behaves as a
|
||||
/// no-op empty filter.
|
||||
pub fn extend_options(
|
||||
this: &mut Option<ContentSourceDataFilter>,
|
||||
other: &Option<ContentSourceDataFilter>,
|
||||
@@ -305,9 +302,9 @@ impl ContentSourceDataFilter {
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes additional information that need to be sent to requests to
|
||||
/// ContentSource. By sending these information ContentSource responses are
|
||||
/// cached-keyed by them and they can access them.
|
||||
/// Describes additional information that need to be sent to requests to [`ContentSource`]. By
|
||||
/// sending these information [`ContentSource`] responses are cached-keyed by them and they can
|
||||
/// access them.
|
||||
#[turbo_tasks::value(shared)]
|
||||
#[derive(Debug, Default, Clone, Hash)]
|
||||
pub struct ContentSourceDataVary {
|
||||
@@ -327,8 +324,8 @@ pub struct ContentSourceDataVary {
|
||||
}
|
||||
|
||||
impl ContentSourceDataVary {
|
||||
/// Merges two vary specification to create a combination of both that cover
|
||||
/// all information requested by either one
|
||||
/// Merges two vary specification to create a combination of both that cover all information
|
||||
/// requested by either one
|
||||
pub fn extend(&mut self, other: &ContentSourceDataVary) {
|
||||
let ContentSourceDataVary {
|
||||
method,
|
||||
@@ -353,8 +350,7 @@ impl ContentSourceDataVary {
|
||||
ContentSourceDataFilter::extend_options(headers, &other.headers);
|
||||
}
|
||||
|
||||
/// Returns true if `self` at least contains all values that the
|
||||
/// argument would contain.
|
||||
/// Returns true if `self` at least contains all values that the argument would contain.
|
||||
pub fn fulfills(&self, other: &ContentSourceDataVary) -> bool {
|
||||
// All fields must be used!
|
||||
let ContentSourceDataVary {
|
||||
|
||||
@@ -21,9 +21,8 @@ use crate::source::{
|
||||
route_tree::RouteTree,
|
||||
};
|
||||
|
||||
/// The result of [`resolve_source_request`]. Similar to a
|
||||
/// `ContentSourceContent`, but without the `Rewrite` variant as this is taken
|
||||
/// care in the function.
|
||||
/// The result of [`resolve_source_request`]. Similar to a [`ContentSourceContent`], but without the
|
||||
/// [`Rewrite`][ContentSourceContent::Rewrite] variant, as this is taken care in the function.
|
||||
#[turbo_tasks::value(serialization = "none", shared)]
|
||||
pub enum ResolveSourceRequestResult {
|
||||
NotFound,
|
||||
@@ -62,14 +61,22 @@ fn get_content_source_content_get_operation(
|
||||
get_content.get(path, data)
|
||||
}
|
||||
|
||||
/// Resolves a [SourceRequest] within a [super::ContentSource], returning the
|
||||
/// corresponding content.
|
||||
/// Resolves a [`SourceRequest`] within a [`ContentSource`], returning the corresponding content.
|
||||
///
|
||||
/// This function is the boundary of consistency. All invoked methods should be
|
||||
/// invoked strongly consistent. This ensures that all requests serve the latest
|
||||
/// version of the content. We don't make resolve_source_request strongly
|
||||
/// consistent as we want get_routes and get to be independent consistent and
|
||||
/// any side effect in get should not wait for recomputing of get_routes.
|
||||
/// Matches the first [`ContentSourceContent`] in the [`RouteTree`] returned by
|
||||
/// [`ContentSource::get_routes`] that does not generate [`ContentSourceContent::Next`].
|
||||
///
|
||||
/// *In the future*, this function may be used at the boundary of consistency. All invoked methods
|
||||
/// should be read using [strong consistency][OperationVc::read_strongly_consistent]. This ensures
|
||||
/// that all requests serve the latest version of the content.
|
||||
///
|
||||
/// If this function is not called/read with strong consistency, [`ContentSource::get_routes`] would
|
||||
/// be allowed to be independently consistent. Side effects should not need to wait for
|
||||
/// recomputation of [`ContentSource::get_routes`].
|
||||
///
|
||||
/// TODO: The callers of this function now read this operation using strong consistency. This may
|
||||
/// have re-introduced performance issues that were solved in
|
||||
/// <https://github.com/vercel/turborepo/pull/5360>.
|
||||
#[turbo_tasks::function(operation)]
|
||||
pub async fn resolve_source_request(
|
||||
source: OperationVc<Box<dyn ContentSource>>,
|
||||
|
||||
@@ -39,17 +39,16 @@ impl BaseSegment {
|
||||
}
|
||||
}
|
||||
|
||||
/// This struct allows to cell a list of RouteTrees and merge them into one.
|
||||
/// This struct allows to cell a list of [`RouteTree`]s and merge them into one.
|
||||
///
|
||||
/// This can't be a single method `fn merge(Vec<Vc<RouteTree>>)` as this would
|
||||
/// lead to creating new tasks over and over. A celled list leads to task reuse
|
||||
/// and faster operation.
|
||||
/// This can't be a single method `fn merge(Vec<Vc<RouteTree>>)` as this would lead to creating new
|
||||
/// tasks over and over. A celled list leads to task reuse and faster operation.
|
||||
#[turbo_tasks::value(transparent)]
|
||||
pub struct RouteTrees(Vec<ResolvedVc<RouteTree>>);
|
||||
|
||||
#[turbo_tasks::value_impl]
|
||||
impl RouteTrees {
|
||||
/// Merges the list of RouteTrees into one RouteTree.
|
||||
/// Merges the list of [`RouteTree`]s into one [`RouteTree`].
|
||||
#[turbo_tasks::function]
|
||||
pub async fn merge(&self) -> Result<Vc<RouteTree>> {
|
||||
let trees = &self.0;
|
||||
|
||||
@@ -7,23 +7,21 @@ use crate::source::{
|
||||
GetContentSourceContents, Rewrite, RewriteType,
|
||||
};
|
||||
|
||||
/// A ContentSourceProcessor handles the final processing of an eventual
|
||||
/// [ContentSourceContent].
|
||||
/// Handles the final processing of an eventual [`ContentSourceContent`].
|
||||
///
|
||||
/// Used in conjunction with [WrappedGetContentSourceContent], this allows a
|
||||
/// [ContentSource] implementation to easily register a final process step over
|
||||
/// some inner ContentSource's fully resolved [ContentSourceResult] and
|
||||
/// [ContentSourceContent].
|
||||
/// Used in conjunction with [`WrappedGetContentSourceContent`], this allows a [`ContentSource`]
|
||||
/// implementation to easily register a final process step over some inner [`ContentSource`]'s fully
|
||||
/// resolved [`ContentSourceContent`].
|
||||
///
|
||||
/// [`ContentSource`]: crate::source::ContentSource
|
||||
#[turbo_tasks::value_trait]
|
||||
pub trait ContentSourceProcessor {
|
||||
#[turbo_tasks::function]
|
||||
fn process(self: Vc<Self>, content: Vc<ContentSourceContent>) -> Vc<ContentSourceContent>;
|
||||
}
|
||||
|
||||
/// A WrappedGetContentSourceContent simply wraps the get_content of a
|
||||
/// [ContentSourceResult], allowing us to process whatever
|
||||
/// [ContentSourceContent] it would have returned.
|
||||
|
||||
/// Wraps the `get_content` of a [`GetContentSourceContent`], allowing us to
|
||||
/// [post-process][ContentSourceProcessor] whatever [`ContentSourceContent`] it returns.
|
||||
#[turbo_tasks::value]
|
||||
pub struct WrappedGetContentSourceContent {
|
||||
inner: ResolvedVc<Box<dyn GetContentSourceContent>>,
|
||||
|
||||
@@ -356,8 +356,11 @@ impl DeclUsage {
|
||||
#[derive(Debug)]
|
||||
pub struct VarGraph {
|
||||
pub values: FxHashMap<Id, VarMeta>,
|
||||
/// Map FreeVar names to their Id to facilitate lookups into [values]
|
||||
/// Doesn't necessarily contain every FreeVar, just those who have non trivial values.
|
||||
|
||||
/// Map [`JsValue::FreeVar`] names to their [`Id`] to facilitate lookups into [`Self::values`].
|
||||
///
|
||||
/// Doesn't necessarily contain every [`FreeVar`][JsValue::FreeVar], just those who have
|
||||
/// non-trivial values.
|
||||
pub free_var_ids: FxHashMap<Atom, Id>,
|
||||
|
||||
pub effects: Vec<Effect>,
|
||||
@@ -381,8 +384,6 @@ impl VarGraph {
|
||||
}
|
||||
}
|
||||
|
||||
/// You should use same [Mark] for this function and
|
||||
/// [swc_ecma_transforms_base::resolver::resolver_with_mark]
|
||||
pub fn create_graph(
|
||||
m: &Program,
|
||||
eval_context: &EvalContext,
|
||||
@@ -417,16 +418,22 @@ pub fn create_graph(
|
||||
/// A context used for assembling the evaluation graph.
|
||||
#[derive(Debug)]
|
||||
pub struct EvalContext {
|
||||
/// Should be the same [`Mark`] used by [`swc_core::ecma::transforms::base::resolver`].
|
||||
pub(crate) unresolved_mark: Mark,
|
||||
/// Should be the same [`Mark`] used by [`swc_core::ecma::transforms::base::resolver`].
|
||||
pub(crate) top_level_mark: Mark,
|
||||
pub(crate) imports: ImportMap,
|
||||
pub(crate) force_free_values: Arc<FxHashSet<Id>>,
|
||||
}
|
||||
|
||||
impl EvalContext {
|
||||
/// Produce a new [EvalContext] from a [Program]. If you wish to support
|
||||
/// webpackIgnore or turbopackIgnore comments, you must pass those in,
|
||||
/// since the AST does not include comments by default.
|
||||
/// Produce a new [`EvalContext`] from a [`Program`].
|
||||
///
|
||||
/// If you wish to support `webpackIgnore` or `turbopackIgnore` comments, you must pass those
|
||||
/// in, since the AST does not include comments by default.
|
||||
///
|
||||
/// You should use the same `unresolved_mark` and `top_level_mark` [Mark] values for this
|
||||
/// context that you passed to [`swc_core::ecma::transforms::base::resolver`].
|
||||
pub fn new(
|
||||
module: Option<&Program>,
|
||||
unresolved_mark: Mark,
|
||||
|
||||
@@ -379,9 +379,10 @@ impl Display for LogicalProperty {
|
||||
}
|
||||
|
||||
/// TODO: Use `Arc`
|
||||
///
|
||||
/// There are 4 kinds of values: Leaves, Nested, Operations, and Placeholders
|
||||
/// (see [JsValueMetaKind] for details). Values are processed in two phases:
|
||||
/// - Analyze phase: We convert AST into [JsValue]s. We don't have contextual information so we need
|
||||
/// (see `JsValueMetaKind` for details). Values are processed in two phases:
|
||||
/// - Analyze phase: We convert AST into `JsValue`s. We don't have contextual information so we need
|
||||
/// to insert placeholders to represent that.
|
||||
/// - Link phase: We try to reduce a value to a constant value. The link phase has 5 substeps that
|
||||
/// are executed on each node in the graph depth-first. When a value is modified, we need to visit
|
||||
|
||||
@@ -24,7 +24,7 @@ use crate::utils::inline_source_map_comment;
|
||||
/// { a } from './data.json'`). This matches webpack's historical behavior.
|
||||
///
|
||||
/// For JSON files larger than 10KB, we use `JSON.parse()` for better performance.
|
||||
/// See: https://v8.dev/blog/cost-of-javascript-2019#json
|
||||
/// See: <https://v8.dev/blog/cost-of-javascript-2019#json>
|
||||
#[turbo_tasks::value]
|
||||
pub struct JsonSourceTransform {
|
||||
/// If true, generate spec-compliant ESM with only an esm default export.
|
||||
|
||||
@@ -33,7 +33,9 @@ use crate::{
|
||||
|
||||
/// A module derived from an original ecmascript module that contains all
|
||||
/// the reexports from that module and also reexports the locals from
|
||||
/// [EcmascriptModuleLocalsModule].
|
||||
/// [`EcmascriptModuleLocalsModule`].
|
||||
///
|
||||
/// [`EcmascriptModuleLocalsModule`]: crate::side_effect_optimization::locals::module::EcmascriptModuleLocalsModule
|
||||
#[turbo_tasks::value]
|
||||
pub struct EcmascriptModuleFacadeModule {
|
||||
module: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||
|
||||
@@ -28,9 +28,11 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
/// A module derived from an original ecmascript module that only contains the
|
||||
/// local declarations, but excludes all reexports. These reexports are exposed
|
||||
/// from [EcmascriptModuleFacadeModule] instead.
|
||||
/// A module derived from an original ecmascript module that only contains the local declarations,
|
||||
/// but excludes all reexports. These reexports are exposed from [`EcmascriptModuleFacadeModule`]
|
||||
/// instead.
|
||||
///
|
||||
/// [`EcmascriptModuleFacadeModule`]: crate::side_effect_optimization::facade::module::EcmascriptModuleFacadeModule
|
||||
#[turbo_tasks::value]
|
||||
pub struct EcmascriptModuleLocalsModule {
|
||||
pub module: ResolvedVc<EcmascriptModuleAsset>,
|
||||
|
||||
@@ -6,8 +6,9 @@ use turbo_tasks_fs::FileSystemPath;
|
||||
|
||||
use crate::TryDotenvProcessEnv;
|
||||
|
||||
/// Loads a series of dotenv files according to the precedence rules set by
|
||||
/// https://nextjs.org/docs/app/building-your-application/configuring/environment-variables#environment-variable-load-order
|
||||
/// Loads a series of dotenv files according to the [precedence rules set by Next.js][precedence].
|
||||
///
|
||||
/// [precedence]: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables#environment-variable-load-order
|
||||
#[turbo_tasks::function]
|
||||
pub async fn load_env(project_path: FileSystemPath) -> Result<Vc<Box<dyn ProcessEnv>>> {
|
||||
let env: Vc<Box<dyn ProcessEnv>> = Vc::upcast(CommandLineProcessEnv::new());
|
||||
|
||||
@@ -523,15 +523,14 @@ impl ProcessArgs {
|
||||
}
|
||||
}
|
||||
|
||||
/// A pool of Node.js workers operating on [entrypoint] with specific [cwd] and
|
||||
/// [env].
|
||||
/// A pool of Node.js workers operating on an `entrypoint` with specific `cwd` and `env`.
|
||||
///
|
||||
/// The pool will spawn processes when needed and reuses old ones. It will never
|
||||
/// spawn more then a certain number of concurrent processes. This is specified
|
||||
/// with the `concurrency` argument in the constructor.
|
||||
/// The pool will spawn processes when needed and reuses old ones. It will never spawn more then a
|
||||
/// certain number of concurrent processes. This is specified with the `concurrency` argument in the
|
||||
/// constructor.
|
||||
///
|
||||
/// The worker will *not* use the env of the parent process by default. All env
|
||||
/// vars need to be provided to make the execution as pure as possible.
|
||||
/// The worker will *not* use the `env` of the parent process by default. All environment variables
|
||||
/// need to be provided to make the execution as pure as possible.
|
||||
#[turbo_tasks::value(cell = "new", serialization = "none", eq = "manual", shared)]
|
||||
pub struct ChildProcessPool {
|
||||
cwd: PathBuf,
|
||||
|
||||
@@ -14,22 +14,22 @@ use turbopack_core::{
|
||||
|
||||
#[derive(Default, Debug, Clone, TraceRawVcs, PartialEq, Eq, NonLocalValue, Encode, Decode)]
|
||||
pub enum TsConfigHandling {
|
||||
/// Ignore tsconfig and jsconfig files
|
||||
/// Ignore tsconfig and jsconfig files.
|
||||
Disabled,
|
||||
#[default]
|
||||
/// Find corresponding tsconfig files based on the location of the file
|
||||
/// Find corresponding tsconfig files based on the location of the file.
|
||||
ContextFile,
|
||||
/// Use the provided config file for all files (if it exists, otherwise fall back to
|
||||
/// ContextFile)
|
||||
/// Use the provided config file for all files if it exists, otherwise fall back to the
|
||||
/// [`Self::ContextFile`] behavior.
|
||||
Fixed(FileSystemPath),
|
||||
}
|
||||
|
||||
#[turbo_tasks::value(shared)]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct ResolveOptionsContext {
|
||||
/// 1. override options.node_externals and
|
||||
/// 2. append environment.resolve_conditions
|
||||
/// 3. override options.extensions
|
||||
/// - Overrides `options.node_externals`
|
||||
/// - Appends `environment.resolve_conditions`
|
||||
/// - Overrides `options.extensions`
|
||||
pub emulate_environment: Option<ResolvedVc<Environment>>,
|
||||
pub enable_types: bool,
|
||||
pub enable_typescript: bool,
|
||||
@@ -93,8 +93,8 @@ impl ResolveOptionsContext {
|
||||
Ok(Self::cell(clone))
|
||||
}
|
||||
|
||||
/// Returns a new [Vc<ResolveOptionsContext>] with its import map extended
|
||||
/// to include the given import map.
|
||||
/// Returns a new [`Vc<ResolveOptionsContext>`][Self] with its import map extended to include
|
||||
/// the given import map.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn with_extended_import_map(
|
||||
self: Vc<Self>,
|
||||
@@ -112,8 +112,8 @@ impl ResolveOptionsContext {
|
||||
Ok(resolve_options_context.cell())
|
||||
}
|
||||
|
||||
/// Returns a new [Vc<ResolveOptionsContext>] with its fallback import map
|
||||
/// extended to include the given import map.
|
||||
/// Returns a new [`Vc<ResolveOptionsContext>`][Self] with its fallback import map extended to
|
||||
/// include the given import map.
|
||||
#[turbo_tasks::function]
|
||||
pub async fn with_extended_fallback_import_map(
|
||||
self: Vc<Self>,
|
||||
|
||||
@@ -35,13 +35,12 @@ impl<T: Send + 'static> ExitGuard<T> {
|
||||
|
||||
type BoxExitFuture = Pin<Box<dyn Future<Output = ()> + Send + 'static>>;
|
||||
|
||||
/// The singular global ExitHandler. This is primarily used to ensure
|
||||
/// `ExitHandler::listen` is only called once.
|
||||
/// The singular global ExitHandler. This is primarily used to ensure `ExitHandler::listen` is only
|
||||
/// called once.
|
||||
///
|
||||
/// The global handler is intentionally not exposed, so that APIs that depend on
|
||||
/// exit behavior are required to take the `ExitHandler`. This ensures that the
|
||||
/// `ExitHandler` is configured before these APIs are run, and that these
|
||||
/// consumers can be used with a callback (e.g. a mock) instead.
|
||||
/// The global handler is intentionally not exposed, so that APIs that depend on exit behavior are
|
||||
/// required to take the `ExitHandler`. This ensures that the `ExitHandler` is configured before
|
||||
/// these APIs are run, and that these consumers can be used with a callback (e.g. a mock) instead.
|
||||
static GLOBAL_EXIT_HANDLER: OnceLock<Arc<ExitHandler>> = OnceLock::new();
|
||||
|
||||
pub struct ExitHandler {
|
||||
@@ -49,19 +48,16 @@ pub struct ExitHandler {
|
||||
}
|
||||
|
||||
impl ExitHandler {
|
||||
/// Waits for `SIGINT` using [`tokio::signal::ctrl_c`], and exits the
|
||||
/// process with exit code `0` after running any futures scheduled with
|
||||
/// [`ExitHandler::on_exit`].
|
||||
/// Waits for `SIGINT` using [`tokio::signal::ctrl_c`], and exits the process with exit code `0`
|
||||
/// after running any futures scheduled with [`ExitHandler::on_exit`].
|
||||
///
|
||||
/// As this uses global process signals, this must only be called once, and
|
||||
/// will panic if called multiple times. Use this when you own the
|
||||
/// process (e.g. `turbopack-cli`).
|
||||
/// As this uses global process signals, this must only be called once, and will panic if called
|
||||
/// multiple times. Use this when you own the process (e.g. `turbopack-cli`).
|
||||
///
|
||||
/// If you don't own the process (e.g. you're called as a library, such as
|
||||
/// in `next-swc`), use [`ExitHandler::new_trigger`] instead.
|
||||
/// If you don't own the process (e.g. you're called as a library, such as in `next-swc`), use
|
||||
/// [`ExitHandler::new_receiver`] instead.
|
||||
///
|
||||
/// This may listen for other signals, like `SIGTERM` or `SIGPIPE` in the
|
||||
/// future.
|
||||
/// This may listen for other signals, like `SIGTERM` or `SIGPIPE` in the future.
|
||||
pub fn listen() -> &'static Arc<ExitHandler> {
|
||||
let (handler, receiver) = Self::new_receiver();
|
||||
if GLOBAL_EXIT_HANDLER.set(handler).is_err() {
|
||||
@@ -77,15 +73,13 @@ impl ExitHandler {
|
||||
GLOBAL_EXIT_HANDLER.get().expect("value is set")
|
||||
}
|
||||
|
||||
/// Creates an [`ExitHandler`] that can be manually controlled with an
|
||||
/// [`ExitReceiver`].
|
||||
/// Creates an [`ExitHandler`] that can be manually controlled with an [`ExitReceiver`].
|
||||
///
|
||||
/// This does not actually exit the process or listen for any signals. If
|
||||
/// you'd like that behavior, use [`ExitHandler::listen`].
|
||||
/// This does not actually exit the process or listen for any signals. If you'd like that
|
||||
/// behavior, use [`ExitHandler::listen`].
|
||||
///
|
||||
/// Because this API has no global side-effects and can be called many times
|
||||
/// within the same process, it is possible to use it to provide a mock
|
||||
/// [`ExitHandler`] inside unit tests.
|
||||
/// Because this API has no global side-effects and can be called many times within the same
|
||||
/// process, it is possible to use it to provide a mock [`ExitHandler`] inside unit tests.
|
||||
pub fn new_receiver() -> (Arc<ExitHandler>, ExitReceiver) {
|
||||
let (tx, rx) = mpsc::unbounded_channel();
|
||||
(Arc::new(ExitHandler { tx }), ExitReceiver { rx })
|
||||
@@ -93,9 +87,8 @@ impl ExitHandler {
|
||||
|
||||
/// Register this given [`Future`] to run upon process exit.
|
||||
///
|
||||
/// As there are many ways for a process be killed that are outside of a
|
||||
/// process's own control (e.g. `SIGKILL` or `SIGSEGV`), this API is
|
||||
/// provided on a best-effort basis.
|
||||
/// As there are many ways for a process be killed that are outside of a process's own control
|
||||
/// (e.g. `SIGKILL` or `SIGSEGV`), this API is provided on a best-effort basis.
|
||||
pub fn on_exit(&self, fut: impl Future<Output = ()> + Send + 'static) {
|
||||
// realistically, this error case can only happen with the `new_receiver` API.
|
||||
self.tx
|
||||
@@ -110,16 +103,14 @@ pub struct ExitReceiver {
|
||||
}
|
||||
|
||||
impl ExitReceiver {
|
||||
/// Call this when the process exits to run the futures scheduled via
|
||||
/// [`ExitHandler::on_exit`].
|
||||
/// Call this when the process exits to run the futures scheduled via [`ExitHandler::on_exit`].
|
||||
///
|
||||
/// As this is intended to be used in a library context, this does not exit
|
||||
/// the process. It is expected that the process will not exit until
|
||||
/// this async method finishes executing.
|
||||
/// As this is intended to be used in a library context, this does not exit the process. It is
|
||||
/// expected that the process will not exit until this async method finishes executing.
|
||||
///
|
||||
/// Additional work can be scheduled using [`ExitHandler::on_exit`] even
|
||||
/// while this is running, and it will execute before this function
|
||||
/// finishes. Work attempted to be scheduled after this finishes will panic.
|
||||
/// Additional work can be scheduled using [`ExitHandler::on_exit`] even while this is running,
|
||||
/// and it will execute before this function finishes. Work attempted to be scheduled after this
|
||||
/// finishes will panic.
|
||||
pub async fn run_exit_handler(mut self) {
|
||||
let mut set = JoinSet::new();
|
||||
while let Ok(fut) = self.rx.try_recv() {
|
||||
|
||||
@@ -49,8 +49,8 @@ fn get_id<S: Subscriber + for<'a> LookupSpan<'a>>(
|
||||
.id
|
||||
}
|
||||
|
||||
/// A tracing layer that writes raw trace data to a writer. The data format is
|
||||
/// defined by [FullTraceRow].
|
||||
/// A tracing layer that writes raw trace data to a writer. We store data using the [`TraceRow`],
|
||||
/// serialized with [`postcard`].
|
||||
pub struct RawTraceLayer<S: Subscriber + for<'a> LookupSpan<'a>> {
|
||||
trace_writer: TraceWriter,
|
||||
start: Instant,
|
||||
|
||||
@@ -48,10 +48,10 @@ impl TraceWriter {
|
||||
/// This is a non-blocking writer that writes a file in a background thread.
|
||||
/// This is inspired by tracing-appender non_blocking, but has some
|
||||
/// differences:
|
||||
/// * It allows writing an owned Vec<u8> instead of a reference, so avoiding additional
|
||||
/// * It allows writing an owned [`Vec<u8>`] instead of a reference, so avoiding additional
|
||||
/// allocation.
|
||||
/// * It uses an unbounded channel to avoid slowing down the application at all (memory) cost.
|
||||
/// * It issues less writes by buffering the data into chunks of WRITE_BUFFER_SIZE, when
|
||||
/// * It issues less writes by buffering the data into chunks of `WRITE_BUFFER_SIZE`, when
|
||||
/// possible.
|
||||
pub fn new<W: Write + Send + 'static>(mut writer: W) -> (Self, TraceWriterGuard) {
|
||||
let (data_tx, data_rx) = unbounded::<Option<TraceInfoBuffer>>();
|
||||
|
||||
@@ -121,32 +121,54 @@ impl WebpackLoaderBuiltinConditionSet for EmptyWebpackLoaderBuiltinConditionSet
|
||||
}
|
||||
}
|
||||
|
||||
/// The kind of decorators transform to use.
|
||||
/// [TODO]: might need bikeshed for the name (Ecma)
|
||||
/// The kind of ECMAScript class decorators transform to use.
|
||||
///
|
||||
/// TODO: might need bikeshed for the name (Ecma)
|
||||
#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, NonLocalValue, Encode, Decode)]
|
||||
pub enum DecoratorsKind {
|
||||
Legacy,
|
||||
/// Enables the syntax and behavior of the modern [stage 3 proposal]. This is the recommended
|
||||
/// transform with JavaScript or [TypeScript 5.0][ts5] or later.
|
||||
///
|
||||
/// [stage 3 proposal]: https://github.com/tc39/proposal-decorators
|
||||
/// [ts5]: https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#differences-with-experimental-legacy-decorators
|
||||
Ecma,
|
||||
|
||||
/// Enables the legacy class decorator syntax and behavior, as it was defined during the [stage
|
||||
/// 1 proposal].
|
||||
///
|
||||
/// This is the same as setting [`jsx.transform.legacyDecorator` in SWC][swc].
|
||||
///
|
||||
/// This option exists for compatibility with the TypeScript compiler's legacy
|
||||
/// `--experimentalDecorators` feature.
|
||||
///
|
||||
/// [stage 1 proposal]: https://github.com/wycats/javascript-decorators/blob/e1bf8d41bfa2591d9/README.md
|
||||
/// [swc]: https://swc.rs/docs/configuration/compilation#jsctransformlegacydecorator
|
||||
Legacy,
|
||||
}
|
||||
|
||||
/// Configuration options for the decorators transform.
|
||||
/// Configuration for the ECMAScript class decorators transform.
|
||||
///
|
||||
/// This is not part of Typescript transform: while there are typescript
|
||||
/// specific transforms (legay decorators), there is an ecma decorator transform
|
||||
/// as well for the JS.
|
||||
/// This is not part of TypeScript transform. It can be used with or without TypeScript.
|
||||
///
|
||||
/// There is a [legacy TypeScript-specific transform][DecoratorsKind::Legacy] available for when
|
||||
/// decorators are used with TypeScript.
|
||||
#[turbo_tasks::value(shared)]
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct DecoratorsOptions {
|
||||
pub decorators_kind: Option<DecoratorsKind>,
|
||||
/// Option to control whether to emit decorator metadata.
|
||||
/// (https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata)
|
||||
/// This'll be applied only if `decorators_type` and
|
||||
/// `enable_typescript_transform` is enabled.
|
||||
/// Option to control whether to [emit decorator metadata]. This will be applied only when
|
||||
/// using [`DecoratorsKind::Legacy`].
|
||||
///
|
||||
/// [emit decorator metadata]: https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata
|
||||
pub emit_decorators_metadata: bool,
|
||||
/// Mimic babel's `decorators.decoratorsBeforeExport` option.
|
||||
/// This'll be applied only if `decorators_type` is enabled.
|
||||
/// ref: https://github.com/swc-project/swc/blob/d4ebb5e6efbed0758f25e46e8f74d7c47ec6cb8f/crates/swc_ecma_parser/src/lib.rs#L327
|
||||
/// [TODO]: this option is not actively being used currently.
|
||||
/// Mimic [Babel's `decorators.decoratorsBeforeExport` option][babel]. This'll be applied only
|
||||
/// if `decorators_type` is enabled.
|
||||
///
|
||||
/// TODO: this option is not currently used.
|
||||
///
|
||||
/// Ref: <https://github.com/swc-project/swc/blob/d4ebb5e6efbed0/crates/swc_ecma_parser/src/lib.rs#L327>
|
||||
///
|
||||
/// [babel]: https://babeljs.io/docs/babel-plugin-proposal-decorators#decoratorsbeforeexport
|
||||
pub decorators_before_export: bool,
|
||||
pub use_define_for_class_fields: bool,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user