Skip to content

Commit

Permalink
add implementation for webpackIgnore and turbopackIgnore
Browse files Browse the repository at this point in the history
  • Loading branch information
arlyon authored and mischnic committed Sep 9, 2024
1 parent 6599b32 commit 8125441
Show file tree
Hide file tree
Showing 26 changed files with 294 additions and 102 deletions.
1 change: 1 addition & 0 deletions crates/next-api/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ impl AppProject {
))),
None,
IssueSeverity::Error.cell(),
false,
)
.resolve()
.await?
Expand Down
1 change: 1 addition & 0 deletions crates/next-api/src/dynamic_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ async fn build_dynamic_imports_map_for_module(
Value::new(EcmaScriptModulesReferenceSubType::DynamicImport),
IssueSeverity::Error.cell(),
None,
false,
)
.first_module()
.await?;
Expand Down
1 change: 1 addition & 0 deletions crates/next-api/src/pages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ impl PagesProject {
Value::new(EcmaScriptModulesReferenceSubType::Undefined),
IssueSeverity::Error.cell(),
None,
false,
)
.first_module()
.await?
Expand Down
1 change: 1 addition & 0 deletions crates/next-core/src/next_client/runtime_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ impl RuntimeEntry {
request,
None,
IssueSeverity::Error.cell(),
false,
)
.resolve()
.await?
Expand Down
1 change: 1 addition & 0 deletions turbopack/crates/turbopack-cli-utils/src/runtime_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ impl RuntimeEntry {
request,
None,
IssueSeverity::Error.cell(),
false,
)
.resolve()
.await?
Expand Down
8 changes: 7 additions & 1 deletion turbopack/crates/turbopack-ecmascript/src/analyzer/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1242,7 +1242,13 @@ impl VisitAstPath for Analyzer<'_> {
if let Some(require_var_id) = extract_var_from_umd_factory(callee, &n.args) {
self.add_value(
require_var_id,
JsValue::WellKnownFunction(WellKnownFunctionKind::Require),
JsValue::WellKnownFunction(WellKnownFunctionKind::Require {
ignore: self
.eval_context
.imports
.get_ignore(n.callee.span())
.unwrap_or_default(),
}),
);
}
}
Expand Down
10 changes: 7 additions & 3 deletions turbopack/crates/turbopack-ecmascript/src/analyzer/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
use indexmap::{IndexMap, IndexSet};
use once_cell::sync::Lazy;
use swc_core::{
common::{comments::Comments, source_map::SmallPos, Span, Spanned},
common::{comments::Comments, source_map::SmallPos, BytePos, Span, Spanned},
ecma::{
ast::*,
atoms::{js_word, JsWord},
Expand Down Expand Up @@ -149,7 +149,7 @@ pub(crate) struct ImportMap {
/// const a = import(/* webpackIgnore: true */ "a");
/// const b = import(/* turbopackIgnore: true */ "b");
/// ```
turbopack_ignores: HashMap<Span, bool>,
pub turbopack_ignores: HashMap<BytePos, bool>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -194,6 +194,10 @@ impl ImportMap {
None
}

pub fn get_ignore(&self, span: Span) -> Option<bool> {
self.turbopack_ignores.get(&span.lo).copied()
}

// TODO this could return &str instead of String to avoid cloning
pub fn get_binding(&self, id: &Id) -> Option<(usize, Option<RcStr>)> {
if let Some((i, i_sym)) = self.imports.get(id) {
Expand Down Expand Up @@ -481,7 +485,7 @@ impl Visit for Analyzer<'_> {
if let Some((callee_span, ignore_statement)) = callee_span.zip(ignore_statement) {
self.data
.turbopack_ignores
.insert(*callee_span, ignore_statement);
.insert(callee_span.lo, ignore_statement);
};
}

Expand Down
35 changes: 23 additions & 12 deletions turbopack/crates/turbopack-ecmascript/src/analyzer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1627,11 +1627,11 @@ impl JsValue {
format!("path.resolve({cwd})"),
"The Node.js path.resolve method: https://nodejs.org/api/path.html#pathresolvepaths",
),
WellKnownFunctionKind::Import => (
WellKnownFunctionKind::Import { .. } => (
"import".to_string(),
"The dynamic import() method from the ESM specification: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports"
),
WellKnownFunctionKind::Require => ("require".to_string(), "The require method from CommonJS"),
WellKnownFunctionKind::Require { .. } => ("require".to_string(), "The require method from CommonJS"),
WellKnownFunctionKind::RequireResolve => ("require.resolve".to_string(), "The require.resolve method from CommonJS"),
WellKnownFunctionKind::RequireContext => ("require.context".to_string(), "The require.context method from webpack"),
WellKnownFunctionKind::RequireContextRequire(..) => ("require.context(...)".to_string(), "The require.context(...) method from webpack: https://webpack.js.org/api/module-methods/#requirecontext"),
Expand Down Expand Up @@ -3626,8 +3626,14 @@ pub enum WellKnownFunctionKind {
PathDirname,
/// `0` is the current working directory.
PathResolve(Box<JsValue>),
Import,
Require,
/// Import and Require can be ignored at compile time using the `turbopackIgnore` directive.
/// This is functionality that was introduced in webpack, so we also support `webpackIgnore`.
Import {
ignore: bool,
},
Require {
ignore: bool,
},
RequireResolve,
RequireContext,
RequireContextRequire(Vc<RequireContextValue>),
Expand Down Expand Up @@ -3656,8 +3662,8 @@ pub enum WellKnownFunctionKind {
impl WellKnownFunctionKind {
pub fn as_define_name(&self) -> Option<&[&str]> {
match self {
Self::Import => Some(&["import"]),
Self::Require => Some(&["require"]),
Self::Import { .. } => Some(&["import"]),
Self::Require { .. } => Some(&["require"]),
Self::RequireResolve => Some(&["require", "resolve"]),
Self::RequireContext => Some(&["require", "context"]),
Self::Define => Some(&["define"]),
Expand Down Expand Up @@ -3704,7 +3710,7 @@ pub mod test_utils {
let mut new_value = match v {
JsValue::Call(
_,
box JsValue::WellKnownFunction(WellKnownFunctionKind::Import),
box JsValue::WellKnownFunction(WellKnownFunctionKind::Import { .. }),
ref args,
) => match &args[0] {
JsValue::Constant(v) => JsValue::Module(ModuleValue {
Expand Down Expand Up @@ -3740,8 +3746,12 @@ pub mod test_utils {
Err(err) => v.into_unknown(true, PrettyPrintError(&err).to_string()),
},
JsValue::FreeVar(ref var) => match &**var {
"import" => JsValue::WellKnownFunction(WellKnownFunctionKind::Import),
"require" => JsValue::WellKnownFunction(WellKnownFunctionKind::Require),
"import" => {
JsValue::WellKnownFunction(WellKnownFunctionKind::Import { ignore: false })
}
"require" => {
JsValue::WellKnownFunction(WellKnownFunctionKind::Require { ignore: false })
}
"define" => JsValue::WellKnownFunction(WellKnownFunctionKind::Define),
"__dirname" => "__dirname".into(),
"__filename" => "__filename".into(),
Expand Down Expand Up @@ -3772,7 +3782,7 @@ mod tests {
use std::{mem::take, path::PathBuf, time::Instant};

use swc_core::{
common::Mark,
common::{comments::SingleThreadedComments, Mark},
ecma::{
ast::EsVersion, parser::parse_file_as_program, transforms::base::resolver,
visit::VisitMutWith,
Expand Down Expand Up @@ -3809,11 +3819,12 @@ mod tests {
r.block_on(async move {
let fm = cm.load_file(&input).unwrap();

let comments = SingleThreadedComments::default();
let mut m = parse_file_as_program(
&fm,
Default::default(),
EsVersion::latest(),
None,
Some(&comments),
&mut vec![],
)
.map_err(|err| err.into_diagnostic(handler).emit())?;
Expand All @@ -3823,7 +3834,7 @@ mod tests {
m.visit_mut_with(&mut resolver(unresolved_mark, top_level_mark, false));

let eval_context =
EvalContext::new(&m, unresolved_mark, top_level_mark, None, None);
EvalContext::new(&m, unresolved_mark, top_level_mark, Some(&comments), None);

let mut var_graph = create_graph(&m, &eval_context);

Expand Down
24 changes: 16 additions & 8 deletions turbopack/crates/turbopack-ecmascript/src/analyzer/well_known.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ pub async fn well_known_function_call(
WellKnownFunctionKind::PathJoin => path_join(args),
WellKnownFunctionKind::PathDirname => path_dirname(args),
WellKnownFunctionKind::PathResolve(cwd) => path_resolve(*cwd, args),
WellKnownFunctionKind::Import => JsValue::unknown(
WellKnownFunctionKind::Import { .. } => JsValue::unknown(
JsValue::call(Box::new(JsValue::WellKnownFunction(kind)), args),
true,
"import() is not supported",
),
WellKnownFunctionKind::Require => require(args),
WellKnownFunctionKind::Require { ignore } => require(args, ignore),
WellKnownFunctionKind::RequireContextRequire(value) => {
require_context_require(value, args).await?
}
Expand Down Expand Up @@ -322,7 +322,11 @@ pub fn path_dirname(mut args: Vec<JsValue>) -> JsValue {
)
}

pub fn require(args: Vec<JsValue>) -> JsValue {
/// Resolve the contents of a require call, throwing errors
/// if we come across any unsupported syntax.
///
/// `ignore` is true if the require call is marked with `turbopackIgnore` or `webpackIgnore`.
pub fn require(args: Vec<JsValue>, ignore: bool) -> JsValue {
if args.len() == 1 {
if let Some(s) = args[0].as_str() {
JsValue::Module(ModuleValue {
Expand All @@ -332,7 +336,9 @@ pub fn require(args: Vec<JsValue>) -> JsValue {
} else {
JsValue::unknown(
JsValue::call(
Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::Require)),
Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::Require {
ignore,
})),
args,
),
true,
Expand All @@ -342,7 +348,9 @@ pub fn require(args: Vec<JsValue>) -> JsValue {
} else {
JsValue::unknown(
JsValue::call(
Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::Require)),
Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::Require {
ignore,
})),
args,
),
true,
Expand Down Expand Up @@ -520,13 +528,13 @@ pub fn path_to_file_url(args: Vec<JsValue>) -> JsValue {

pub fn well_known_function_member(kind: WellKnownFunctionKind, prop: JsValue) -> (JsValue, bool) {
let new_value = match (kind, prop.as_str()) {
(WellKnownFunctionKind::Require, Some("resolve")) => {
(WellKnownFunctionKind::Require { .. }, Some("resolve")) => {
JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve)
}
(WellKnownFunctionKind::Require, Some("cache")) => {
(WellKnownFunctionKind::Require { .. }, Some("cache")) => {
JsValue::WellKnownObject(WellKnownObjectKind::RequireCache)
}
(WellKnownFunctionKind::Require, Some("context")) => {
(WellKnownFunctionKind::Require { .. }, Some("context")) => {
JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContext)
}
(WellKnownFunctionKind::RequireContextRequire(val), Some("resolve")) => {
Expand Down
10 changes: 9 additions & 1 deletion turbopack/crates/turbopack-ecmascript/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ impl EcmascriptParsable for EcmascriptModuleAsset {
impl EcmascriptAnalyzable for EcmascriptModuleAsset {
#[turbo_tasks::function]
fn analyze(self: Vc<Self>) -> Vc<AnalyzeEcmascriptModuleResult> {
analyse_ecmascript_module(self, None, None)
analyse_ecmascript_module(self, None)
}

/// Generates module contents without an analysis pass. This is useful for
Expand Down Expand Up @@ -417,6 +417,7 @@ impl EcmascriptModuleAsset {
pub fn new(
source: Vc<Box<dyn Source>>,
asset_context: Vc<Box<dyn AssetContext>>,

ty: Value<EcmascriptModuleAssetType>,
transforms: Vc<EcmascriptInputTransforms>,
options: Vc<EcmascriptOptions>,
Expand All @@ -428,6 +429,7 @@ impl EcmascriptModuleAsset {
ty: ty.into_value(),
transforms,
options,

compile_time_info,
inner_assets: None,
last_successful_parse: Default::default(),
Expand All @@ -440,6 +442,7 @@ impl EcmascriptModuleAsset {
asset_context: Vc<Box<dyn AssetContext>>,
ty: Value<EcmascriptModuleAssetType>,
transforms: Vc<EcmascriptInputTransforms>,

options: Vc<EcmascriptOptions>,
compile_time_info: Vc<CompileTimeInfo>,
inner_assets: Vc<InnerAssets>,
Expand All @@ -461,6 +464,11 @@ impl EcmascriptModuleAsset {
Ok(self.await?.source)
}

#[turbo_tasks::function]
pub fn analyze(self: Vc<Self>) -> Vc<AnalyzeEcmascriptModuleResult> {
analyse_ecmascript_module(self, None)
}

#[turbo_tasks::function]
pub async fn options(self: Vc<Self>) -> Result<Vc<EcmascriptOptions>> {
Ok(self.await?.options)
Expand Down
6 changes: 3 additions & 3 deletions turbopack/crates/turbopack-ecmascript/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ async fn parse_internal(
FileContent::Content(file) => match file.content().to_str() {
Ok(string) => {
let transforms = &*transforms.await?;
match parse_content(
match parse_file_content(
string.into_owned(),
fs_path_vc,
fs_path,
Expand Down Expand Up @@ -246,7 +246,7 @@ async fn parse_internal(
})
}

async fn parse_content(
async fn parse_file_content(
string: String,
fs_path_vc: Vc<FileSystemPath>,
fs_path: &FileSystemPath,
Expand Down Expand Up @@ -433,7 +433,7 @@ async fn parse_content(
&parsed_program,
unresolved_mark,
top_level_mark,
None,
Some(&comments),
Some(source),
);

Expand Down
2 changes: 2 additions & 0 deletions turbopack/crates/turbopack-ecmascript/src/references/amd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ impl ModuleReference for AmdDefineAssetReference {
self.request,
Some(self.issue_source),
try_to_severity(self.in_try),
/* ignore */ false,
)
}
}
Expand Down Expand Up @@ -160,6 +161,7 @@ impl CodeGenerateable for AmdDefineWithDependenciesCodeGen {
*request,
Some(self.issue_source),
try_to_severity(self.in_try),
false,
),
Value::new(ChunkItem),
)
Expand Down
Loading

0 comments on commit 8125441

Please sign in to comment.