Skip to content

Commit 06b23af

Browse files
authored
feat: inline const for leaf modules (#10451)
1 parent 6adfebf commit 06b23af

File tree

66 files changed

+1268
-521
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1268
-521
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ rustc-hash = { version = "2.1.0" }
7373
scopeguard = "1.2.0"
7474
serde = { version = "1.0.217" }
7575
serde_json = { version = "1.0.134" }
76+
sftrace-setup = { version = "0.1.0" }
7677
sha2 = { version = "0.10.8" }
7778
simd-json = { version = "0.14.3" }
7879
smol_str = { version = "0.3.0" }
@@ -87,7 +88,6 @@ url = { version = "2.5.4" }
8788
urlencoding = { version = "2.1.3" }
8889
ustr = { package = "ustr-fxhash", version = "1.0.1" }
8990
xxhash-rust = { version = "0.8.14" }
90-
sftrace-setup = { version = "0.1.0" }
9191

9292
# Pinned
9393
napi = { version = "3.0.0-beta.8" }

crates/node_binding/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ tokio = { workspace = true, features = ["rt", "
110110
ustr = { workspace = true }
111111

112112
[target.'cfg(not(target_family = "wasm"))'.dependencies]
113-
tokio = { workspace = true, features = ["parking_lot"] }
114113
rspack_tracing = { workspace = true }
115-
sftrace-setup = { workspace = true, optional = true }
114+
sftrace-setup = { workspace = true, optional = true }
115+
tokio = { workspace = true, features = ["parking_lot"] }
116116

117117
[build-dependencies]
118118
napi-build = { workspace = true }

crates/node_binding/binding.d.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,7 @@ export interface JsRsdoctorModule {
10591059
belongModules: Array<number>
10601060
chunks: Array<number>
10611061
issuerPath: Array<number>
1062-
bailoutReason?: string
1062+
bailoutReason: Array<string>
10631063
}
10641064

10651065
export interface JsRsdoctorModuleGraph {
@@ -1885,6 +1885,7 @@ parallelCodeSplitting: boolean
18851885
rspackFuture?: RawRspackFuture
18861886
cache: boolean | { type: "persistent" } & RawExperimentCacheOptionsPersistent | { type: "memory" }
18871887
useInputFileSystem?: false | Array<RegExp>
1888+
inlineConst: boolean
18881889
}
18891890

18901891
export interface RawExperimentSnapshotOptions {
@@ -2094,6 +2095,11 @@ export interface RawJavascriptParserOptions {
20942095
* @experimental
20952096
*/
20962097
importDynamic?: boolean
2098+
/**
2099+
* This option is experimental in Rspack only and subject to change or be removed anytime.
2100+
* @experimental
2101+
*/
2102+
inlineConst?: boolean
20972103
}
20982104

20992105
export interface RawJsonGeneratorOptions {

crates/node_binding/src/raw_options/raw_experiments/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub struct RawExperiments {
2626
pub cache: RawExperimentCacheOptions,
2727
#[napi(ts_type = "false | Array<RegExp>")]
2828
pub use_input_file_system: Option<WithFalse<Vec<RspackRegex>>>,
29+
pub inline_const: bool,
2930
}
3031

3132
impl From<RawExperiments> for Experiments {
@@ -43,6 +44,7 @@ impl From<RawExperiments> for Experiments {
4344
top_level_await: value.top_level_await,
4445
rspack_future: value.rspack_future.unwrap_or_default().into(),
4546
cache: normalize_raw_experiment_cache_options(value.cache),
47+
inline_const: value.inline_const,
4648
}
4749
}
4850
}

crates/node_binding/src/raw_options/raw_module/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,9 @@ pub struct RawJavascriptParserOptions {
289289
/// This option is experimental in Rspack only and subject to change or be removed anytime.
290290
/// @experimental
291291
pub import_dynamic: Option<bool>,
292+
/// This option is experimental in Rspack only and subject to change or be removed anytime.
293+
/// @experimental
294+
pub inline_const: Option<bool>,
292295
}
293296

294297
impl From<RawJavascriptParserOptions> for JavascriptParserOptions {
@@ -329,6 +332,7 @@ impl From<RawJavascriptParserOptions> for JavascriptParserOptions {
329332
require_dynamic: value.require_dynamic,
330333
require_resolve: value.require_resolve,
331334
import_dynamic: value.import_dynamic,
335+
inline_const: value.inline_const,
332336
}
333337
}
334338
}

crates/rspack/src/builder/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,7 @@ impl ModuleOptionsBuilder {
17121712
require_dynamic: Some(true),
17131713
require_resolve: Some(true),
17141714
import_dynamic: Some(true),
1715+
inline_const: Some(false),
17151716
..Default::default()
17161717
}),
17171718
);
@@ -3667,6 +3668,8 @@ pub struct ExperimentsBuilder {
36673668
parallel_code_splitting: Option<bool>,
36683669
/// Whether to enable async web assembly.
36693670
async_web_assembly: Option<bool>,
3671+
/// Whether to enable inline constants.
3672+
inline_const: Option<bool>,
36703673
// TODO: lazy compilation
36713674
}
36723675

@@ -3683,6 +3686,7 @@ impl From<Experiments> for ExperimentsBuilder {
36833686
future_defaults: None,
36843687
css: None,
36853688
async_web_assembly: None,
3689+
inline_const: Some(value.inline_const),
36863690
}
36873691
}
36883692
}
@@ -3700,6 +3704,7 @@ impl From<&mut ExperimentsBuilder> for ExperimentsBuilder {
37003704
css: value.css.take(),
37013705
parallel_code_splitting: value.parallel_code_splitting.take(),
37023706
async_web_assembly: value.async_web_assembly.take(),
3707+
inline_const: value.inline_const.take(),
37033708
}
37043709
}
37053710
}
@@ -3791,6 +3796,7 @@ impl ExperimentsBuilder {
37913796
w!(self.output_module, false);
37923797

37933798
let parallel_code_splitting = d!(self.parallel_code_splitting, false);
3799+
let inline_const = d!(self.inline_const, production);
37943800

37953801
Ok(Experiments {
37963802
layers,
@@ -3799,6 +3805,7 @@ impl ExperimentsBuilder {
37993805
rspack_future,
38003806
parallel_code_splitting,
38013807
cache,
3808+
inline_const,
38023809
})
38033810
}
38043811
}

crates/rspack/tests/snapshots/defaults__default_options.snap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,9 @@ CompilerOptions {
14171417
import_dynamic: Some(
14181418
true,
14191419
),
1420+
inline_const: Some(
1421+
false,
1422+
),
14201423
},
14211424
),
14221425
},
@@ -1453,6 +1456,7 @@ CompilerOptions {
14531456
top_level_await: true,
14541457
rspack_future: RspackFuture,
14551458
cache: Disabled,
1459+
inline_const: false,
14561460
},
14571461
node: Some(
14581462
NodeOption {

crates/rspack_core/src/concatenated_module.rs

Lines changed: 104 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ use crate::{
4242
define_es_module_flag_statement, filter_runtime, impl_source_map_config, merge_runtime_condition,
4343
merge_runtime_condition_non_false, module_update_hash, property_access, property_name,
4444
reserved_names::RESERVED_NAMES, returning_function, runtime_condition_expression,
45-
subtract_runtime_condition, to_identifier, AsyncDependenciesBlockIdentifier, BoxDependency,
46-
BoxDependencyTemplate, BoxModuleDependency, BuildContext, BuildInfo, BuildMeta,
45+
subtract_runtime_condition, to_identifier, to_normal_comment, AsyncDependenciesBlockIdentifier,
46+
BoxDependency, BoxDependencyTemplate, BoxModuleDependency, BuildContext, BuildInfo, BuildMeta,
4747
BuildMetaDefaultObject, BuildMetaExportsType, BuildResult, ChunkGraph, ChunkInitFragments,
4848
ChunkRenderContext, CodeGenerationDataTopLevelDeclarations, CodeGenerationExportsFinalNames,
4949
CodeGenerationPublicPathAutoReplace, CodeGenerationResult, Compilation, ConcatenatedModuleIdent,
@@ -53,7 +53,7 @@ use crate::{
5353
LibIdentOptions, MaybeDynamicTargetExportInfoHashKey, Module, ModuleArgument, ModuleGraph,
5454
ModuleGraphCacheArtifact, ModuleGraphConnection, ModuleIdentifier, ModuleLayer, ModuleType,
5555
PrefetchExportsInfoMode, Resolve, RuntimeCondition, RuntimeGlobals, RuntimeSpec, SourceType,
56-
SpanExt, Template, UsageState, DEFAULT_EXPORT, NAMESPACE_OBJECT_EXPORT,
56+
SpanExt, UsageState, UsedName, UsedNameItem, DEFAULT_EXPORT, NAMESPACE_OBJECT_EXPORT,
5757
};
5858

5959
type ExportsDefinitionArgs = Vec<(String, String)>;
@@ -991,6 +991,7 @@ impl Module for ConcatenatedModule {
991991

992992
let mut exports_map: HashMap<Atom, String> = HashMap::default();
993993
let mut unused_exports: HashSet<Atom> = HashSet::default();
994+
let mut inlined_exports: HashSet<Atom> = HashSet::default();
994995

995996
let root_info = module_to_info_map
996997
.get(&self.root_module_ctxt.id)
@@ -1021,6 +1022,10 @@ impl Module for ConcatenatedModule {
10211022
unused_exports.insert(name);
10221023
continue;
10231024
};
1025+
let UsedNameItem::Str(used_name) = used_name else {
1026+
inlined_exports.insert(name);
1027+
continue;
1028+
};
10241029
exports_map.insert(used_name.clone(), {
10251030
let final_name = Self::get_final_name(
10261031
&compilation.get_module_graph(),
@@ -1164,6 +1169,13 @@ impl Module for ConcatenatedModule {
11641169
join_atom(unused_exports.iter(), ", ")
11651170
)));
11661171
}
1172+
// List inlined exports
1173+
if !inlined_exports.is_empty() {
1174+
result.add(RawStringSource::from(format!(
1175+
"\n// INLINED EXPORTS: {}\n",
1176+
join_atom(inlined_exports.iter(), ", ")
1177+
)));
1178+
}
11671179

11681180
let mut namespace_object_sources: IdentifierMap<String> = IdentifierMap::default();
11691181

@@ -1210,7 +1222,7 @@ impl Module for ConcatenatedModule {
12101222
continue;
12111223
}
12121224

1213-
if let Some(used_name) =
1225+
if let Some(UsedNameItem::Str(used_name)) =
12141226
ExportInfoGetter::get_used_name(export_info.as_data(&module_graph), None, runtime)
12151227
{
12161228
let final_name = Self::get_final_name(
@@ -2256,16 +2268,36 @@ impl ConcatenatedModule {
22562268
if let Some(used_name) =
22572269
ExportsInfoGetter::get_used_name(&exports_info, runtime, &export_name)
22582270
{
2259-
// https://github.com/webpack/webpack/blob/1f99ad6367f2b8a6ef17cce0e058f7a67fb7db18/lib/optimize/ConcatenatedModule.js#L402-L404
2260-
let used_name = used_name.to_used_name_vec();
2261-
2262-
return Binding::Symbol(SymbolBinding {
2263-
info_id: info.module,
2264-
name: direct_export.as_str().into(),
2265-
ids: used_name[1..].to_vec(),
2266-
export_name,
2267-
comment: None,
2268-
});
2271+
match used_name {
2272+
UsedName::Normal(used_name) => {
2273+
// https://github.com/webpack/webpack/blob/1f99ad6367f2b8a6ef17cce0e058f7a67fb7db18/lib/optimize/ConcatenatedModule.js#L402-L404
2274+
return Binding::Symbol(SymbolBinding {
2275+
info_id: info.module,
2276+
name: direct_export.as_str().into(),
2277+
ids: used_name[1..].to_vec(),
2278+
export_name,
2279+
comment: None,
2280+
});
2281+
}
2282+
UsedName::Inlined(inlined) => {
2283+
return Binding::Raw(RawBinding {
2284+
raw_name: format!(
2285+
"{} {}",
2286+
to_normal_comment(&format!(
2287+
"inlined export {}",
2288+
property_access(&export_name, 0)
2289+
)),
2290+
inlined.render()
2291+
)
2292+
.into(),
2293+
// Inlined export is definitely a terminal binding
2294+
ids: vec![],
2295+
export_name,
2296+
info_id: info.module,
2297+
comment: None,
2298+
});
2299+
}
2300+
}
22692301
} else {
22702302
return Binding::Raw(RawBinding {
22712303
raw_name: "/* unused export */ undefined".into(),
@@ -2335,20 +2367,29 @@ impl ConcatenatedModule {
23352367
// That's how webpack write https://github.com/webpack/webpack/blob/1f99ad6367f2b8a6ef17cce0e058f7a67fb7db18/lib/optimize/ConcatenatedModule.js#L463-L471
23362368
let used_name = ExportsInfoGetter::get_used_name(&exports_info, runtime, &export_name)
23372369
.expect("should have export name");
2338-
2339-
let used_name = used_name.to_used_name_vec();
2340-
return Binding::Raw(RawBinding {
2341-
info_id: info.module,
2342-
raw_name: info
2343-
.namespace_object_name
2344-
.as_ref()
2345-
.expect("should have raw name")
2346-
.as_str()
2347-
.into(),
2348-
ids: used_name,
2349-
export_name,
2350-
comment: None,
2351-
});
2370+
return match used_name {
2371+
UsedName::Normal(used_name) => Binding::Raw(RawBinding {
2372+
info_id: info.module,
2373+
raw_name: info
2374+
.namespace_object_name
2375+
.as_ref()
2376+
.expect("should have raw name")
2377+
.as_str()
2378+
.into(),
2379+
ids: used_name,
2380+
export_name,
2381+
comment: None,
2382+
}),
2383+
// Inlined namespace export symbol is not possible for now but we compat it here
2384+
UsedName::Inlined(inlined) => Binding::Raw(RawBinding {
2385+
info_id: info.module,
2386+
raw_name: inlined.render().into(),
2387+
// Inlined export is definitely a terminal binding
2388+
ids: vec![],
2389+
export_name,
2390+
comment: None,
2391+
}),
2392+
};
23522393
}
23532394

23542395
panic!(
@@ -2361,24 +2402,41 @@ impl ConcatenatedModule {
23612402
if let Some(used_name) =
23622403
ExportsInfoGetter::get_used_name(&exports_info, runtime, &export_name)
23632404
{
2364-
let used_name = used_name.to_used_name_vec();
2365-
let comment = if used_name == export_name {
2366-
String::new()
2367-
} else {
2368-
Template::to_normal_comment(&join_atom(export_name.iter(), ","))
2369-
};
2370-
Binding::Raw(RawBinding {
2371-
raw_name: format!(
2372-
"{}{}",
2373-
info.name.as_ref().expect("should have name"),
2374-
comment
2375-
)
2376-
.into(),
2377-
ids: used_name,
2378-
export_name,
2379-
info_id: info.module,
2380-
comment: None,
2381-
})
2405+
match used_name {
2406+
UsedName::Normal(used_name) => {
2407+
let comment = if used_name == export_name {
2408+
String::new()
2409+
} else {
2410+
to_normal_comment(&property_access(&export_name, 0))
2411+
};
2412+
Binding::Raw(RawBinding {
2413+
raw_name: format!(
2414+
"{}{}",
2415+
info.name.as_ref().expect("should have name"),
2416+
comment
2417+
)
2418+
.into(),
2419+
ids: used_name,
2420+
export_name,
2421+
info_id: info.module,
2422+
comment: None,
2423+
})
2424+
}
2425+
UsedName::Inlined(inlined) => {
2426+
let comment = to_normal_comment(&format!(
2427+
"inlined export {}",
2428+
property_access(&export_name, 0)
2429+
));
2430+
Binding::Raw(RawBinding {
2431+
raw_name: format!("{}{}", inlined.render(), comment).into(),
2432+
// Inlined export is definitely a terminal binding
2433+
ids: vec![],
2434+
export_name,
2435+
info_id: info.module,
2436+
comment: None,
2437+
})
2438+
}
2439+
}
23822440
} else {
23832441
Binding::Raw(RawBinding {
23842442
raw_name: "/* unused export */ undefined".into(),

crates/rspack_core/src/dependency/context_element_dependency.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,11 @@ impl Dependency for ContextElementDependency {
123123
referenced_exports
124124
.iter()
125125
.map(|export| {
126-
ExtendedReferencedExport::Export(ReferencedExport::new(vec![export.clone()], false))
126+
ExtendedReferencedExport::Export(ReferencedExport::new(
127+
vec![export.clone()],
128+
false,
129+
false,
130+
))
127131
})
128132
.collect_vec()
129133
} else {

0 commit comments

Comments
 (0)