Skip to content
Open
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/rspack_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ heck = { workspace = true }
hex = { workspace = true }
indexmap = { workspace = true, features = ["rayon"] }
indoc = { workspace = true }
inventory = { workspace = true }
itertools = { workspace = true }
json = { workspace = true }
mime_guess = { workspace = true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,23 @@ use crate::{
pub fn render_lexical_declarations(
fields: RuntimeGlobals,
render_runtime_global: Option<&dyn Fn(RuntimeGlobals) -> Option<String>>,
) -> String {
render_lexical_declarations_with_name(fields, render_runtime_global, &|runtime_global| {
runtime_global.to_lexical_name().map(str::to_string)
})
}

fn render_lexical_declarations_with_name(
fields: RuntimeGlobals,
render_runtime_global: Option<&dyn Fn(RuntimeGlobals) -> Option<String>>,
render_lexical_name: &dyn Fn(RuntimeGlobals) -> Option<String>,
) -> String {
let names = fields
.renderable_require_scope()
.difference(RuntimeGlobals::REQUIRE | RuntimeGlobals::REQUIRE_SCOPE)
.iter_names()
.filter_map(|(_, runtime_global)| {
let lexical_name = runtime_global.to_lexical_name()?;
let lexical_name = render_lexical_name(runtime_global)?;
if let Some(render_runtime_global) = render_runtime_global
&& let Some(value) = render_runtime_global(runtime_global)
{
Expand All @@ -28,7 +38,7 @@ pub fn render_lexical_declarations(
} else if runtime_global.should_initialize_as_array() {
Some(format!("{lexical_name}=[]"))
} else {
Some(lexical_name.to_string())
Some(lexical_name)
}
})
.collect::<Vec<_>>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ impl TaskContext {
false,
compiler_context,
);
compilation.runtime_template =
RuntimeTemplate::for_module_execution(self.compiler_options.clone());
compilation.dependency_factories = self.dependency_factories.clone();
compilation.dependency_templates = self.dependency_templates.clone();
std::mem::swap(
Expand Down
2 changes: 1 addition & 1 deletion crates/rspack_core/src/dependency/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use rspack_cacheable::{
};
pub use runtime_requirements_dependency::{
CodeGenerationRuntimeRequirementsWrite, RuntimeRequirementsDependency,
RuntimeRequirementsDependencyTemplate,
RuntimeRequirementsDependencyTemplate, RuntimeRequirementsDependencyWriteOperation,
};
use rustc_hash::{FxHashMap, FxHashSet};
use serde::Serialize;
Expand Down
115 changes: 114 additions & 1 deletion crates/rspack_core/src/dependency/runtime_requirements_dependency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,51 @@ use rspack_hash::{RspackHash, RspackHasher};

use crate::{
Compilation, DependencyCodeGeneration, DependencyRange, DependencyTemplate,
DependencyTemplateType, RuntimeGlobals, RuntimeSpec, TemplateContext, TemplateReplaceSource,
DependencyTemplateType, RuntimeGlobals, RuntimeGlobalsRenderMode, RuntimeSpec, TemplateContext,
TemplateReplaceSource,
};

#[cacheable]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RuntimeRequirementsDependencyWriteOperation {
Assign,
Add,
Subtract,
Multiply,
Divide,
Remainder,
LeftShift,
RightShift,
UnsignedRightShift,
BitwiseOr,
BitwiseXor,
BitwiseAnd,
Exponentiation,
LogicalAnd,
LogicalOr,
NullishCoalescing,
}

impl RspackHash for RuntimeRequirementsDependencyWriteOperation {
fn hash(&self, state: &mut RspackHasher) {
(*self as u8).hash(state);
}
}

#[cacheable]
#[derive(Debug, Clone, Copy)]
pub struct RuntimeRequirementsDependencyWriteInfo {
pub value_range: DependencyRange,
pub operation: RuntimeRequirementsDependencyWriteOperation,
}

impl RspackHash for RuntimeRequirementsDependencyWriteInfo {
fn hash(&self, state: &mut RspackHasher) {
self.value_range.hash(state);
self.operation.hash(state);
}
}

#[cacheable]
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub enum RuntimeRequirementsDependencyMode {
Expand Down Expand Up @@ -53,12 +95,14 @@ pub struct RuntimeRequirementsDependency {
pub range: DependencyRange,
pub runtime_requirements: RuntimeGlobals,
pub mode: RuntimeRequirementsDependencyMode,
pub write_info: Option<RuntimeRequirementsDependencyWriteInfo>,
}

impl RspackHash for RuntimeRequirementsDependency {
fn hash(&self, state: &mut RspackHasher) {
"runtime_requirements".hash(state);
self.runtime_requirements.hash(state);
self.write_info.hash(state);
match self.mode {
RuntimeRequirementsDependencyMode::Normal => {
"range".hash(state);
Expand Down Expand Up @@ -108,34 +152,55 @@ impl RuntimeRequirementsDependency {
range,
runtime_requirements,
mode: RuntimeRequirementsDependencyMode::Normal,
write_info: None,
}
}
pub fn call(range: DependencyRange, runtime_requirements: RuntimeGlobals) -> Self {
Self {
range,
runtime_requirements,
mode: RuntimeRequirementsDependencyMode::Call,
write_info: None,
}
}
pub fn add_only(runtime_requirements: RuntimeGlobals) -> Self {
Self {
range: DependencyRange::default(),
runtime_requirements,
mode: RuntimeRequirementsDependencyMode::AddOnly,
write_info: None,
}
}
pub fn write(range: DependencyRange, runtime_requirements: RuntimeGlobals) -> Self {
Self {
range,
runtime_requirements,
mode: RuntimeRequirementsDependencyMode::Write,
write_info: None,
}
}
pub fn write_assignment(
range: DependencyRange,
value_range: DependencyRange,
operation: RuntimeRequirementsDependencyWriteOperation,
runtime_requirements: RuntimeGlobals,
) -> Self {
Self {
range,
runtime_requirements,
mode: RuntimeRequirementsDependencyMode::Write,
write_info: Some(RuntimeRequirementsDependencyWriteInfo {
value_range,
operation,
}),
}
}
pub fn write_only(runtime_requirements: RuntimeGlobals) -> Self {
Self {
range: DependencyRange::default(),
runtime_requirements,
mode: RuntimeRequirementsDependencyMode::WriteOnly,
write_info: None,
}
}
pub fn unsupported_require_property(
Expand All @@ -146,6 +211,7 @@ impl RuntimeRequirementsDependency {
range,
runtime_requirements,
mode: RuntimeRequirementsDependencyMode::UnsupportedRequireProperty,
write_info: None,
}
}
}
Expand Down Expand Up @@ -226,6 +292,53 @@ impl DependencyTemplate for RuntimeRequirementsDependencyTemplate {
if matches!(dep.mode, RuntimeRequirementsDependencyMode::WriteOnly) {
return;
}
if code_generatable_context.runtime_template.render_mode()
== RuntimeGlobalsRenderMode::RspackExport
&& let Some(write_info) = dep.write_info
&& let Some(setter) = code_generatable_context
.runtime_template
.render_runtime_global_setter(&dep.runtime_requirements)
{
let runtime_global = code_generatable_context
.runtime_template
.render_runtime_globals(&dep.runtime_requirements);
let prefix = match write_info.operation {
RuntimeRequirementsDependencyWriteOperation::Assign => format!("{setter}("),
RuntimeRequirementsDependencyWriteOperation::LogicalAnd => {
format!("{runtime_global} && {setter}(")
}
RuntimeRequirementsDependencyWriteOperation::LogicalOr => {
format!("{runtime_global} || {setter}(")
}
RuntimeRequirementsDependencyWriteOperation::NullishCoalescing => {
format!("{runtime_global} ?? {setter}(")
}
operation => {
let operator = match operation {
RuntimeRequirementsDependencyWriteOperation::Add => "+",
RuntimeRequirementsDependencyWriteOperation::Subtract => "-",
RuntimeRequirementsDependencyWriteOperation::Multiply => "*",
RuntimeRequirementsDependencyWriteOperation::Divide => "/",
RuntimeRequirementsDependencyWriteOperation::Remainder => "%",
RuntimeRequirementsDependencyWriteOperation::LeftShift => "<<",
RuntimeRequirementsDependencyWriteOperation::RightShift => ">>",
RuntimeRequirementsDependencyWriteOperation::UnsignedRightShift => ">>>",
RuntimeRequirementsDependencyWriteOperation::BitwiseOr => "|",
RuntimeRequirementsDependencyWriteOperation::BitwiseXor => "^",
RuntimeRequirementsDependencyWriteOperation::BitwiseAnd => "&",
RuntimeRequirementsDependencyWriteOperation::Exponentiation => "**",
RuntimeRequirementsDependencyWriteOperation::Assign
| RuntimeRequirementsDependencyWriteOperation::LogicalAnd
| RuntimeRequirementsDependencyWriteOperation::LogicalOr
| RuntimeRequirementsDependencyWriteOperation::NullishCoalescing => unreachable!(),
};
format!("{setter}({runtime_global} {operator} ")
}
};
source.replace(dep.range.start, write_info.value_range.start, prefix, None);
source.insert(write_info.value_range.end, ")".to_string(), None);
return;
}
let content = code_generatable_context
.runtime_template
.render_runtime_globals(&dep.runtime_requirements);
Expand Down
1 change: 1 addition & 0 deletions crates/rspack_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ pub use rspack_location::{
};
pub mod concatenated_module;
pub mod reserved_names;
pub use inventory;
use rspack_cacheable::{cacheable, with::AsPreset};
use rspack_hash::{RspackHash, RspackHasher};
pub use rspack_loader_runner::{
Expand Down
21 changes: 21 additions & 0 deletions crates/rspack_core/src/runtime_globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,18 @@ pub fn rspack_runtime_variable_name(runtime_variable: &RuntimeVariable) -> &'sta
}
}

pub fn rspack_export_runtime_variable_name(runtime_variable: &RuntimeVariable) -> &'static str {
match *runtime_variable {
RuntimeVariable::Require => "rspackRequire",
RuntimeVariable::Context => "context",
RuntimeVariable::Modules => "modules",
RuntimeVariable::ModuleCache => "moduleCache",
RuntimeVariable::Exports => "exports",
RuntimeVariable::Module => "module",
RuntimeVariable::StartupExec => "startupExec",
}
}

pub fn runtime_variable_name(runtime_variable: &RuntimeVariable) -> &'static str {
match *runtime_variable {
RuntimeVariable::Require => "__webpack_require__",
Expand Down Expand Up @@ -603,6 +615,15 @@ impl RuntimeGlobals {
RUNTIME_GLOBAL_MAP.3.get(self).map(String::as_str)
}

pub fn to_rspack_export_setter_name(&self) -> Option<String> {
let name = self.to_lexical_name()?;
let mut setter = String::with_capacity(name.len() + 3);
setter.push_str("set");
setter.push(name.as_bytes()[0].to_ascii_uppercase() as char);
setter.push_str(&name[1..]);
Some(setter)
}

pub fn should_initialize_as_object(&self) -> bool {
!self.intersection(*INITIALIZE_OBJECT_GLOBALS).is_empty()
}
Expand Down
23 changes: 23 additions & 0 deletions crates/rspack_core/src/runtime_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,17 @@ pub trait RuntimeModule:
fn template(&self) -> Vec<(String, String)> {
vec![]
}
/// Names that this runtime module may declare in the surrounding chunk scope.
///
/// Runtime modules backed by EJS templates should derive these names from top-level `var()` and
/// `fn()` declarations. `#[impl_runtime_module(runtime_module_variables)]` registers the provider
/// so the names can be reserved before runtime module instances are created.
fn runtime_module_variables() -> &'static [&'static str]
where
Self: Sized,
{
&[]
}
async fn generate(
&self,
context: &RuntimeModuleGenerateContext<'_>,
Expand All @@ -266,6 +277,18 @@ pub trait RuntimeModule:
}
}

pub struct RuntimeModuleVariableProvider {
pub variables: fn() -> &'static [&'static str],
}

inventory::collect!(RuntimeModuleVariableProvider);

pub fn all_runtime_module_variables() -> impl Iterator<Item = &'static str> {
inventory::iter::<RuntimeModuleVariableProvider>
.into_iter()
.flat_map(|provider| (provider.variables)().iter().copied())
}

pub trait AttachableRuntimeModule {
fn attach(&mut self, chunk: ChunkUkey);
}
Expand Down
Loading
Loading