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
73 changes: 41 additions & 32 deletions turbopack/crates/turbopack-ecmascript/src/analyzer/imports.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, collections::BTreeMap, fmt::Display};
use std::{borrow::Cow, collections::BTreeMap, fmt::Display, sync::Arc};

use once_cell::sync::Lazy;
use rustc_hash::{FxHashMap, FxHashSet};
Expand Down Expand Up @@ -60,10 +60,8 @@ static ANNOTATION_CHUNKING_TYPE: Lazy<Wtf8Atom> =
static ATTRIBUTE_MODULE_TYPE: Lazy<Wtf8Atom> = Lazy::new(|| atom!("type").into());

impl ImportAnnotations {
pub fn parse(with: Option<&ObjectLit>) -> ImportAnnotations {
let Some(with) = with else {
return ImportAnnotations::default();
};
pub fn parse(with: Option<&ObjectLit>) -> Option<ImportAnnotations> {
let with = with?;

let mut map = BTreeMap::new();
let mut turbopack_loader_name: Option<RcStr> = None;
Expand Down Expand Up @@ -148,11 +146,19 @@ impl ImportAnnotations {
options: turbopack_loader_options,
});

ImportAnnotations {
map,
turbopack_loader,
turbopack_rename_as,
turbopack_module_type,
if !map.is_empty()
|| turbopack_loader.is_some()
|| turbopack_rename_as.is_some()
|| turbopack_module_type.is_some()
{
Some(ImportAnnotations {
map,
turbopack_loader,
turbopack_rename_as,
turbopack_module_type,
})
} else {
None
}
}

Expand Down Expand Up @@ -181,12 +187,16 @@ impl ImportAnnotations {
);
}

Some(ImportAnnotations {
map,
turbopack_loader: None,
turbopack_rename_as: None,
turbopack_module_type: None,
})
if !map.is_empty() {
Some(ImportAnnotations {
map,
turbopack_loader: None,
turbopack_rename_as: None,
turbopack_module_type: None,
})
} else {
None
}
}

/// Returns the content on the transition annotation
Expand Down Expand Up @@ -395,7 +405,7 @@ pub(crate) enum ImportedSymbol {
pub(crate) struct ImportMapReference {
pub module_path: Wtf8Atom,
pub imported_symbol: ImportedSymbol,
pub annotations: ImportAnnotations,
pub annotations: Option<Arc<ImportAnnotations>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would a Box instead of Arc be better?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arc:

references/jsonwebtoken.js/full
                        time:   [47.028 ms 47.163 ms 47.306 ms]
                        change: [-2.4739% -1.5284% -0.6681%] (p = 0.00 < 0.05)
                        Change within noise threshold.

Box:

references/jsonwebtoken.js/full
                        time:   [48.934 ms 49.123 ms 49.358 ms]
                        change: [+3.6630% +4.1558% +4.7521%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 11 outliers among 100 measurements (11.00%)
  8 (8.00%) high mild
  3 (3.00%) high severe

pub issue_source: Option<IssueSource>,
}

Expand Down Expand Up @@ -581,7 +591,7 @@ impl Analyzer<'_> {
span: Span,
module_path: Wtf8Atom,
imported_symbol: ImportedSymbol,
annotations: ImportAnnotations,
annotations: Option<ImportAnnotations>,
) -> Option<usize> {
let issue_source = self
.source
Expand All @@ -591,7 +601,7 @@ impl Analyzer<'_> {
module_path,
imported_symbol,
issue_source,
annotations,
annotations: annotations.map(Arc::new),
};
if let Some(i) = self.data.references.get_index_of(&r) {
Some(i)
Expand Down Expand Up @@ -897,11 +907,11 @@ impl Visit for Analyzer<'_> {
_ => None,
};

let attributes = parse_directives(comments, n.args.first());

if let Some((callee_span, attributes)) = callee_span.zip(attributes) {
if let Some(callee_span) = callee_span
&& let Some(attributes) = parse_directives(comments, n.args.first())
{
self.data.attributes.insert(callee_span.lo, attributes);
};
}
}

n.visit_children_with(self);
Expand All @@ -915,11 +925,11 @@ impl Visit for Analyzer<'_> {
_ => None,
};

let attributes = parse_directives(comments, n.args.iter().flatten().next());

if let Some((callee_span, attributes)) = callee_span.zip(attributes) {
if let Some(callee_span) = callee_span
&& let Some(attributes) = parse_directives(comments, n.args.iter().flatten().next())
{
self.data.attributes.insert(callee_span.lo, attributes);
};
}
}

n.visit_children_with(self);
Expand Down Expand Up @@ -1069,7 +1079,7 @@ mod tests {
props: vec![kv_prop(ident_key("turbopackLoader"), str_lit("raw-loader"))],
};

let annotations = ImportAnnotations::parse(Some(&with));
let annotations = ImportAnnotations::parse(Some(&with)).unwrap();
assert!(annotations.has_turbopack_loader());

let loader = annotations.turbopack_loader().unwrap();
Expand All @@ -1091,7 +1101,7 @@ mod tests {
],
};

let annotations = ImportAnnotations::parse(Some(&with));
let annotations = ImportAnnotations::parse(Some(&with)).unwrap();
assert!(annotations.has_turbopack_loader());

let loader = annotations.turbopack_loader().unwrap();
Expand All @@ -1107,15 +1117,14 @@ mod tests {
props: vec![kv_prop(ident_key("type"), str_lit("json"))],
};

let annotations = ImportAnnotations::parse(Some(&with));
let annotations = ImportAnnotations::parse(Some(&with)).unwrap();
assert!(!annotations.has_turbopack_loader());
assert!(annotations.module_type().is_some());
}

#[test]
fn test_parse_empty_with() {
let annotations = ImportAnnotations::parse(None);
assert!(!annotations.has_turbopack_loader());
assert!(annotations.module_type().is_none());
assert!(annotations.is_none());
}
}
30 changes: 23 additions & 7 deletions turbopack/crates/turbopack-ecmascript/src/analyzer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::{
};

use anyhow::{Result, bail};
use either::Either;
use num_bigint::BigInt;
use num_traits::identities::Zero;
use once_cell::sync::Lazy;
Expand Down Expand Up @@ -268,7 +269,7 @@ impl Display for ConstantValue {
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct ModuleValue {
pub module: Wtf8Atom,
pub annotations: ImportAnnotations,
pub annotations: Option<Arc<ImportAnnotations>>,
}

#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
Expand Down Expand Up @@ -799,7 +800,16 @@ impl Display for JsValue {
module: name,
annotations,
}) => {
write!(f, "Module({}, {annotations})", name.to_string_lossy())
write!(
f,
"Module({}, {})",
name.to_string_lossy(),
if let Some(annotations) = annotations {
Either::Left(annotations)
} else {
Either::Right("{}")
}
)
}
JsValue::Unknown { .. } => write!(f, "???"),
JsValue::WellKnownObject(obj) => write!(f, "WellKnownObject({obj:?})"),
Expand Down Expand Up @@ -1618,7 +1628,15 @@ impl JsValue {
module: name,
annotations,
}) => {
format!("module<{}, {annotations}>", name.to_string_lossy())
format!(
"module<{}, {}>",
name.to_string_lossy(),
if let Some(annotations) = annotations {
Either::Left(annotations)
} else {
Either::Right("{}")
}
)
}
JsValue::Unknown {
original_value: inner,
Expand Down Expand Up @@ -3527,9 +3545,7 @@ pub mod test_utils {
};
use crate::{
analyzer::{
RequireContextValue,
builtin::replace_builtin,
imports::{ImportAnnotations, ImportAttributes},
RequireContextValue, builtin::replace_builtin, imports::ImportAttributes,
parse_require_context,
},
utils::module_value_to_well_known_object,
Expand Down Expand Up @@ -3557,7 +3573,7 @@ pub mod test_utils {
JsValue::Constant(ConstantValue::Str(v)) => {
JsValue::promise(JsValue::Module(ModuleValue {
module: v.as_atom().into_owned().into(),
annotations: ImportAnnotations::default(),
annotations: None,
}))
}
_ => v.into_unknown(true, "import() non constant"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ use turbopack_core::compile_time_info::CompileTimeInfo;
use url::Url;

use super::{
ConstantValue, JsValue, JsValueUrlKind, ModuleValue, WellKnownFunctionKind,
WellKnownObjectKind, imports::ImportAnnotations,
ConstantValue, JsValue, JsValueUrlKind, ModuleValue, WellKnownFunctionKind, WellKnownObjectKind,
};
use crate::analyzer::RequireContextValue;

Expand Down Expand Up @@ -359,7 +358,7 @@ pub fn import(args: Vec<JsValue>) -> JsValue {
[JsValue::Constant(ConstantValue::Str(v))] => {
JsValue::promise(JsValue::Module(ModuleValue {
module: v.as_atom().into_owned().into(),
annotations: ImportAnnotations::default(),
annotations: None,
}))
}
_ => JsValue::unknown(
Expand All @@ -380,7 +379,7 @@ fn require(args: Vec<JsValue>) -> JsValue {
if let Some(s) = args[0].as_str() {
JsValue::Module(ModuleValue {
module: s.into(),
annotations: ImportAnnotations::default(),
annotations: None,
})
} else {
JsValue::unknown(
Expand Down Expand Up @@ -448,7 +447,7 @@ fn require_context_require(val: RequireContextValue, args: Vec<JsValue>) -> Resu

Ok(JsValue::Module(ModuleValue {
module: m.to_string().into(),
annotations: ImportAnnotations::default(),
annotations: None,
}))
}

Expand Down
35 changes: 24 additions & 11 deletions turbopack/crates/turbopack-ecmascript/src/references/esm/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,13 +322,13 @@ impl EsmAssetReferences {

#[turbo_tasks::value(shared)]
#[derive(Hash, Debug, ValueToString)]
#[value_to_string("import {request} with {annotations}")]
#[value_to_string("import {request}")]
pub struct EsmAssetReference {
pub module: ResolvedVc<EcmascriptModuleAsset>,
pub origin: ResolvedVc<Box<dyn ResolveOrigin>>,
// Request is a string to avoid eagerly parsing into a `Request` VC
pub request: RcStr,
pub annotations: ImportAnnotations,
pub annotations: Option<ImportAnnotations>,
pub issue_source: IssueSource,
pub export_name: Option<ModulePart>,
pub import_usage: ImportUsage,
Expand All @@ -339,7 +339,7 @@ pub struct EsmAssetReference {

impl EsmAssetReference {
fn get_origin(&self) -> Vc<Box<dyn ResolveOrigin>> {
if let Some(transition) = self.annotations.transition() {
if let Some(transition) = self.annotations.as_ref().and_then(|a| a.transition()) {
self.origin.with_transition(transition.into())
} else {
*self.origin
Expand All @@ -353,7 +353,7 @@ impl EsmAssetReference {
origin: ResolvedVc<Box<dyn ResolveOrigin>>,
request: RcStr,
issue_source: IssueSource,
annotations: ImportAnnotations,
annotations: Option<ImportAnnotations>,
export_name: Option<ModulePart>,
import_usage: ImportUsage,
import_externals: bool,
Expand All @@ -378,7 +378,7 @@ impl EsmAssetReference {
origin: ResolvedVc<Box<dyn ResolveOrigin>>,
request: RcStr,
issue_source: IssueSource,
annotations: ImportAnnotations,
annotations: Option<ImportAnnotations>,
export_name: Option<ModulePart>,
import_usage: ImportUsage,
import_externals: bool,
Expand Down Expand Up @@ -406,7 +406,8 @@ impl EsmAssetReference {
impl ModuleReference for EsmAssetReference {
#[turbo_tasks::function]
async fn resolve_reference(&self) -> Result<Vc<ModuleResolveResult>> {
let ty = if let Some(loader) = self.annotations.turbopack_loader() {
let ty = if let Some(loader) = self.annotations.as_ref().and_then(|a| a.turbopack_loader())
{
// Resolve the loader path relative to the importing file
let origin = self.get_origin();
let origin_path = origin.origin_path().await?;
Expand All @@ -428,10 +429,18 @@ impl ModuleReference for EsmAssetReference {
loader: loader_fs_path,
options: loader.options.clone(),
},
rename_as: self.annotations.turbopack_rename_as().cloned(),
module_type: self.annotations.turbopack_module_type().cloned(),
rename_as: self
.annotations
.as_ref()
.and_then(|a| a.turbopack_rename_as())
.cloned(),
module_type: self
.annotations
.as_ref()
.and_then(|a| a.turbopack_module_type())
.cloned(),
}
} else if let Some(module_type) = self.annotations.module_type() {
} else if let Some(module_type) = self.annotations.as_ref().and_then(|a| a.module_type()) {
EcmaScriptModulesReferenceSubType::ImportWithType(RcStr::from(
&*module_type.to_string_lossy(),
))
Expand Down Expand Up @@ -498,7 +507,8 @@ impl ModuleReference for EsmAssetReference {

fn chunking_type(&self) -> Option<ChunkingType> {
self.annotations
.chunking_type()
.as_ref()
.and_then(|a| a.chunking_type())
.unwrap_or(Some(ChunkingType::Parallel {
inherit_async: true,
hoisted: true,
Expand Down Expand Up @@ -534,7 +544,10 @@ impl EsmAssetReference {
}

// only chunked references can be imported
if !matches!(this.annotations.chunking_type(), Some(None)) {
if !matches!(
this.annotations.as_ref().and_then(|a| a.chunking_type()),
Some(None)
) {
let import_externals = this.import_externals;
let referenced_asset = self.get_referenced_asset().await?;

Expand Down
Loading
Loading