Skip to content

Commit 11a1564

Browse files
committed
Turbopack: Remove undocumented legacy syntax for built-in conditions (e.g. foreign, browser)
1 parent 7ef1eaa commit 11a1564

File tree

7 files changed

+107
-184
lines changed

7 files changed

+107
-184
lines changed

crates/next-core/src/next_config.rs

Lines changed: 44 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::{collections::BTreeSet, str::FromStr};
2-
31
use anyhow::{Context, Result, bail};
42
use either::Either;
53
use rustc_hash::FxHashSet;
@@ -667,21 +665,11 @@ impl TryFrom<ConfigConditionItem> for ConditionItem {
667665
}
668666
}
669667

670-
#[derive(
671-
Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, NonLocalValue, OperationValue,
672-
)]
673-
#[serde(rename_all = "camelCase", untagged)]
674-
pub enum RuleConfigItem {
675-
Options(RuleConfigItemOptions),
676-
LegacyConditional(FxIndexMap<RcStr, RuleConfigItem>),
677-
LegacyBoolean(bool),
678-
}
679-
680668
#[derive(
681669
Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, NonLocalValue, OperationValue,
682670
)]
683671
#[serde(rename_all = "camelCase")]
684-
pub struct RuleConfigItemOptions {
672+
pub struct RuleConfigItem {
685673
pub loaders: Vec<LoaderItem>,
686674
#[serde(default, alias = "as")]
687675
pub rename_as: Option<RcStr>,
@@ -1401,11 +1389,7 @@ impl NextConfig {
14011389
}
14021390

14031391
#[turbo_tasks::function]
1404-
pub async fn webpack_rules(
1405-
&self,
1406-
active_conditions: BTreeSet<WebpackLoaderBuiltinCondition>,
1407-
project_path: FileSystemPath,
1408-
) -> Result<Vc<WebpackRules>> {
1392+
pub async fn webpack_rules(&self, project_path: FileSystemPath) -> Result<Vc<WebpackRules>> {
14091393
let Some(turbo_rules) = self.turbopack.as_ref().and_then(|t| t.rules.as_ref()) else {
14101394
return Ok(Vc::cell(Vec::new()));
14111395
};
@@ -1429,43 +1413,6 @@ impl NextConfig {
14291413
.collect(),
14301414
)
14311415
}
1432-
enum FindRuleResult<'a> {
1433-
Found(&'a RuleConfigItemOptions),
1434-
NotFound,
1435-
Break,
1436-
}
1437-
// This logic is needed for the `LegacyConditional`/`LegacyBoolean` configuration
1438-
// syntax. This is technically public syntax, but was never documented and it is
1439-
// unlikely that anyone is depending on it (outside of some Next.js internals).
1440-
fn find_rule<'a>(
1441-
rule: &'a RuleConfigItem,
1442-
active_conditions: &BTreeSet<WebpackLoaderBuiltinCondition>,
1443-
) -> FindRuleResult<'a> {
1444-
match rule {
1445-
RuleConfigItem::Options(rule) => FindRuleResult::Found(rule),
1446-
RuleConfigItem::LegacyConditional(map) => {
1447-
for (condition, rule) in map.iter() {
1448-
let condition = WebpackLoaderBuiltinCondition::from_str(condition);
1449-
if let Ok(condition) = condition
1450-
&& (condition == WebpackLoaderBuiltinCondition::Default
1451-
|| active_conditions.contains(&condition))
1452-
{
1453-
match find_rule(rule, active_conditions) {
1454-
FindRuleResult::Found(rule) => {
1455-
return FindRuleResult::Found(rule);
1456-
}
1457-
FindRuleResult::Break => {
1458-
return FindRuleResult::Break;
1459-
}
1460-
FindRuleResult::NotFound => {}
1461-
}
1462-
}
1463-
}
1464-
FindRuleResult::NotFound
1465-
}
1466-
RuleConfigItem::LegacyBoolean(_) => FindRuleResult::Break,
1467-
}
1468-
}
14691416
let config_file_path = || project_path.join(&self.config_file_name);
14701417
for item in &rule_collection.0 {
14711418
match item {
@@ -1479,55 +1426,52 @@ impl NextConfig {
14791426
},
14801427
));
14811428
}
1482-
RuleConfigCollectionItem::Full(rule_config_item) => {
1483-
if let FindRuleResult::Found(RuleConfigItemOptions {
1484-
loaders,
1485-
rename_as,
1486-
condition,
1487-
}) = find_rule(rule_config_item, &active_conditions)
1429+
RuleConfigCollectionItem::Full(RuleConfigItem {
1430+
loaders,
1431+
rename_as,
1432+
condition,
1433+
}) => {
1434+
// If the extension contains a wildcard, and the rename_as does not,
1435+
// emit an issue to prevent users from encountering duplicate module
1436+
// names.
1437+
if glob.contains("*")
1438+
&& let Some(rename_as) = rename_as.as_ref()
1439+
&& !rename_as.contains("*")
14881440
{
1489-
// If the extension contains a wildcard, and the rename_as does not,
1490-
// emit an issue to prevent users from encountering duplicate module
1491-
// names.
1492-
if glob.contains("*")
1493-
&& let Some(rename_as) = rename_as.as_ref()
1494-
&& !rename_as.contains("*")
1495-
{
1496-
InvalidLoaderRuleRenameAsIssue {
1497-
glob: glob.clone(),
1441+
InvalidLoaderRuleRenameAsIssue {
1442+
glob: glob.clone(),
1443+
config_file_path: config_file_path()?,
1444+
rename_as: rename_as.clone(),
1445+
}
1446+
.resolved_cell()
1447+
.emit();
1448+
}
1449+
1450+
// convert from Next.js-specific condition type to internal Turbopack
1451+
// condition type
1452+
let condition = if let Some(condition) = condition {
1453+
if let Ok(cond) = ConditionItem::try_from(condition.clone()) {
1454+
Some(cond)
1455+
} else {
1456+
InvalidLoaderRuleConditionIssue {
1457+
condition: condition.clone(),
14981458
config_file_path: config_file_path()?,
1499-
rename_as: rename_as.clone(),
15001459
}
15011460
.resolved_cell()
15021461
.emit();
1503-
}
1504-
1505-
// convert from Next.js-specific condition type to internal Turbopack
1506-
// condition type
1507-
let condition = if let Some(condition) = condition {
1508-
if let Ok(cond) = ConditionItem::try_from(condition.clone()) {
1509-
Some(cond)
1510-
} else {
1511-
InvalidLoaderRuleConditionIssue {
1512-
condition: condition.clone(),
1513-
config_file_path: config_file_path()?,
1514-
}
1515-
.resolved_cell()
1516-
.emit();
1517-
None
1518-
}
1519-
} else {
15201462
None
1521-
};
1522-
rules.push((
1523-
glob.clone(),
1524-
LoaderRuleItem {
1525-
loaders: transform_loaders(Box::new(loaders.iter())),
1526-
rename_as: rename_as.clone(),
1527-
condition,
1528-
},
1529-
));
1530-
}
1463+
}
1464+
} else {
1465+
None
1466+
};
1467+
rules.push((
1468+
glob.clone(),
1469+
LoaderRuleItem {
1470+
loaders: transform_loaders(Box::new(loaders.iter())),
1471+
rename_as: rename_as.clone(),
1472+
condition,
1473+
},
1474+
));
15311475
}
15321476
}
15331477
}
@@ -2001,11 +1945,11 @@ mod tests {
20011945
}
20021946
});
20031947

2004-
let rule_config: RuleConfigItemOptions = serde_json::from_value(json_value).unwrap();
1948+
let rule_config: RuleConfigItem = serde_json::from_value(json_value).unwrap();
20051949

20061950
assert_eq!(
20071951
rule_config,
2008-
RuleConfigItemOptions {
1952+
RuleConfigItem {
20091953
loaders: vec![],
20101954
rename_as: Some(rcstr!("*.js")),
20111955
condition: Some(ConfigConditionItem::All(

crates/next-core/src/next_shared/webpack_rules/babel.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ use regex::Regex;
55
use turbo_rcstr::{RcStr, rcstr};
66
use turbo_tasks::{ResolvedVc, Vc};
77
use turbo_tasks_fs::{self, FileSystemEntryType, FileSystemPath};
8-
use turbopack::module_options::LoaderRuleItem;
8+
use turbopack::module_options::{ConditionItem, LoaderRuleItem};
99
use turbopack_core::{
1010
issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString},
1111
reference_type::{CommonJsReferenceSubType, ReferenceType},
1212
resolve::{node::node_cjs_resolve_options, parse::Request, pattern::Pattern, resolve},
1313
};
1414
use turbopack_node::transforms::webpack::WebpackLoaderItem;
1515

16+
use crate::next_shared::webpack_rules::WebpackLoaderBuiltinCondition;
17+
1618
// https://babeljs.io/docs/config-files
1719
// TODO: Also support a `babel` key in a package.json file
1820
const BABEL_CONFIG_FILES: &[&str] = &[
@@ -89,7 +91,9 @@ pub async fn get_babel_loader_rules(
8991
options: Default::default(),
9092
}]),
9193
rename_as: Some(rcstr!("*")),
92-
condition: None,
94+
condition: Some(ConditionItem::Not(Box::new(ConditionItem::Builtin(
95+
RcStr::from(WebpackLoaderBuiltinCondition::Foreign.as_str()),
96+
)))),
9397
},
9498
)])
9599
}

crates/next-core/src/next_shared/webpack_rules/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub async fn webpack_loader_options(
149149
builtin_conditions: BTreeSet<WebpackLoaderBuiltinCondition>,
150150
) -> Result<Vc<OptionWebpackLoadersOptions>> {
151151
let mut rules = next_config
152-
.webpack_rules(builtin_conditions.clone(), project_path.clone())
152+
.webpack_rules(project_path.clone())
153153
.owned()
154154
.await?;
155155

packages/next/src/build/swc/index.ts

Lines changed: 31 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import type {
1616
TurbopackRuleCondition,
1717
TurbopackRuleConfigCollection,
1818
TurbopackRuleConfigItem,
19-
TurbopackRuleConfigItemOptions,
2019
} from '../../server/config-shared'
2120
import { isDeepStrictEqual } from 'util'
2221
import { type DefineEnvOptions, getDefineEnv } from '../define-env'
@@ -836,29 +835,32 @@ function bindingToApi(
836835

837836
for (const key of ruleKeys) {
838837
nextConfig.turbopack.conditions[`#reactCompiler/${key}`] = {
839-
path: key,
840-
content:
841-
options.compilationMode === 'annotation'
842-
? /['"]use memo['"]/
843-
: !options.compilationMode ||
844-
options.compilationMode === 'infer'
845-
? // Matches declaration or useXXX or </ (closing jsx) or /> (self closing jsx)
846-
/['"]use memo['"]|\Wuse[A-Z]|<\/|\/>/
847-
: undefined,
838+
all: [
839+
'browser',
840+
{ not: 'foreign' },
841+
{
842+
path: key,
843+
content:
844+
options.compilationMode === 'annotation'
845+
? /['"]use memo['"]/
846+
: !options.compilationMode ||
847+
options.compilationMode === 'infer'
848+
? // Matches declaration or useXXX or </ (closing jsx) or /> (self closing jsx)
849+
/['"]use memo['"]|\Wuse[A-Z]|<\/|\/>/
850+
: undefined,
851+
},
852+
],
848853
}
849854
nextConfig.turbopack.rules[`#reactCompiler/${key}`] = {
850-
browser: {
851-
foreign: false,
852-
loaders: [
853-
getReactCompilerLoader(
854-
reactCompilerOptions,
855-
projectPath,
856-
nextConfig.dev,
857-
/* isServer */ false,
858-
/* reactCompilerExclude */ undefined
859-
),
860-
],
861-
},
855+
loaders: [
856+
getReactCompilerLoader(
857+
reactCompilerOptions,
858+
projectPath,
859+
nextConfig.dev,
860+
/* isServer */ false,
861+
/* reactCompilerExclude */ undefined
862+
),
863+
],
862864
}
863865
}
864866
}
@@ -1039,26 +1041,14 @@ function bindingToApi(
10391041
glob: string
10401042
): any {
10411043
if (!rule) return rule
1044+
for (const item of rule.loaders) {
1045+
checkLoaderItem(item, glob)
1046+
}
10421047
let serializedRule: any = rule
1043-
if ('loaders' in rule) {
1044-
const narrowedRule = rule as TurbopackRuleConfigItemOptions
1045-
for (const item of narrowedRule.loaders) {
1046-
checkLoaderItem(item, glob)
1047-
}
1048-
if (narrowedRule.condition != null) {
1049-
serializedRule = {
1050-
...rule,
1051-
condition: serializeRuleCondition(narrowedRule.condition),
1052-
}
1053-
}
1054-
} else {
1055-
serializedRule = {}
1056-
for (const [key, value] of Object.entries(rule)) {
1057-
if (typeof value === 'object' && value) {
1058-
serializedRule[key] = serializeConfigItem(value, glob)
1059-
} else {
1060-
serializedRule[key] = value
1061-
}
1048+
if (rule.condition != null) {
1049+
serializedRule = {
1050+
...rule,
1051+
condition: serializeRuleCondition(rule.condition),
10621052
}
10631053
}
10641054
return serializedRule

packages/next/src/server/config-schema.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import type {
1111
DeprecatedExperimentalTurboOptions,
1212
TurbopackOptions,
1313
TurbopackRuleConfigItem,
14-
TurbopackRuleConfigItemOptions,
1514
TurbopackRuleConfigCollection,
1615
TurbopackRuleCondition,
1716
TurbopackLoaderBuiltinCondition,
@@ -135,26 +134,17 @@ const zTurbopackCondition: zod.ZodType<TurbopackRuleCondition> = z.union([
135134
}),
136135
])
137136

138-
const zTurbopackRuleConfigItemOptions: zod.ZodType<TurbopackRuleConfigItemOptions> =
137+
const zTurbopackRuleConfigItem: zod.ZodType<TurbopackRuleConfigItem> =
139138
z.strictObject({
140139
loaders: z.array(zTurbopackLoaderItem),
141140
as: z.string().optional(),
142141
condition: zTurbopackCondition.optional(),
143142
})
144143

145-
const zTurbopackRuleConfigItem: zod.ZodType<TurbopackRuleConfigItem> = z.union([
146-
z.literal(false),
147-
z.record(
148-
zTurbopackLoaderBuiltinCondition,
149-
z.lazy(() => zTurbopackRuleConfigItem)
150-
),
151-
zTurbopackRuleConfigItemOptions,
152-
])
153-
154144
const zTurbopackRuleConfigCollection: zod.ZodType<TurbopackRuleConfigCollection> =
155145
z.union([
156146
zTurbopackRuleConfigItem,
157-
z.array(z.union([zTurbopackLoaderItem, zTurbopackRuleConfigItemOptions])),
147+
z.array(z.union([zTurbopackLoaderItem, zTurbopackRuleConfigItem])),
158148
])
159149

160150
const zTurbopackConfig: zod.ZodType<TurbopackOptions> = z.strictObject({

packages/next/src/server/config-shared.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -278,17 +278,12 @@ export type TurbopackRuleCondition =
278278
content?: RegExp
279279
}
280280

281-
export type TurbopackRuleConfigItemOptions = {
281+
export type TurbopackRuleConfigItem = {
282282
loaders: TurbopackLoaderItem[]
283283
as?: string
284284
condition?: TurbopackRuleCondition
285285
}
286286

287-
export type TurbopackRuleConfigItem =
288-
| TurbopackRuleConfigItemOptions
289-
| { [condition in TurbopackLoaderBuiltinCondition]?: TurbopackRuleConfigItem }
290-
| false
291-
292287
/**
293288
* This can be an object representing a single configuration, or a list of
294289
* loaders and/or rule configuration objects.
@@ -300,7 +295,7 @@ export type TurbopackRuleConfigItem =
300295
*/
301296
export type TurbopackRuleConfigCollection =
302297
| TurbopackRuleConfigItem
303-
| (TurbopackLoaderItem | TurbopackRuleConfigItemOptions)[]
298+
| (TurbopackLoaderItem | TurbopackRuleConfigItem)[]
304299

305300
export interface TurbopackOptions {
306301
/**

0 commit comments

Comments
 (0)