Skip to content

Commit

Permalink
fix: trusted type with devtool eval (#7866)
Browse files Browse the repository at this point in the history
  • Loading branch information
LingyuCoder committed Sep 12, 2024
1 parent b1bf153 commit f6f1798
Show file tree
Hide file tree
Showing 13 changed files with 635 additions and 205 deletions.
3 changes: 3 additions & 0 deletions crates/rspack_core/src/dependency/dependency_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ pub enum DependencyType {
NewUrl,
// new Worker()
NewWorker,
// create script url
CreateScriptUrl,
// import.meta.webpackHot.accept
ImportMetaHotAccept,
// import.meta.webpackHot.decline
Expand Down Expand Up @@ -118,6 +120,7 @@ impl DependencyType {
DependencyType::CjsSelfReference => "cjs self exports reference",
DependencyType::NewUrl => "new URL()",
DependencyType::NewWorker => "new Worker()",
DependencyType::CreateScriptUrl => "create script url",
DependencyType::ImportMetaHotAccept => "import.meta.webpackHot.accept",
DependencyType::ImportMetaHotDecline => "import.meta.webpackHot.decline",
DependencyType::ModuleHotAccept => "module.hot.accept",
Expand Down
32 changes: 29 additions & 3 deletions crates/rspack_plugin_devtool/src/eval_dev_tool_module_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use rspack_core::{
ApplyContext, BoxModule, ChunkInitFragments, ChunkUkey, Compilation, CompilationParams,
CompilerCompilation, CompilerOptions, Plugin, PluginContext,
};
use rspack_core::{CompilationAdditionalTreeRuntimeRequirements, RuntimeGlobals};
use rspack_error::Result;
use rspack_hash::RspackHash;
use rspack_hook::{plugin, plugin_hook};
Expand Down Expand Up @@ -83,6 +84,7 @@ async fn eval_devtool_plugin_compilation(
hooks
.inline_in_runtime_bailout
.tap(eval_devtool_plugin_inline_in_runtime_bailout::new(self));

Ok(())
}

Expand Down Expand Up @@ -135,11 +137,16 @@ fn eval_devtool_plugin_render_module_content(
.trim_start_matches('/')
)
);
// TODO: Implement support for the trustedTypes option.
// This will depend on the additionalModuleRuntimeRequirements hook.

let module_content =
simd_json::to_string(&format!("{source}{footer}")).expect("failed to parse string");
RawSource::from(format!(
"eval({});",
simd_json::to_string(&format!("{source}{footer}")).expect("failed to parse string")
if compilation.options.output.trusted_types.is_some() {
format!("{}({})", RuntimeGlobals::CREATE_SCRIPT, module_content)
} else {
module_content
}
))
.boxed()
};
Expand Down Expand Up @@ -183,10 +190,29 @@ impl Plugin for EvalDevToolModulePlugin {
.compiler_hooks
.compilation
.tap(eval_devtool_plugin_compilation::new(self));
ctx
.context
.compilation_hooks
.additional_tree_runtime_requirements
.tap(eval_devtool_plugin_additional_tree_runtime_requirements::new(self));
Ok(())
}
}

#[plugin_hook(CompilationAdditionalTreeRuntimeRequirements for EvalDevToolModulePlugin)]
async fn eval_devtool_plugin_additional_tree_runtime_requirements(
&self,
compilation: &mut Compilation,
_chunk_ukey: &ChunkUkey,
runtime_requirements: &mut RuntimeGlobals,
) -> Result<()> {
if compilation.options.output.trusted_types.is_some() {
runtime_requirements.insert(RuntimeGlobals::CREATE_SCRIPT);
}

Ok(())
}

// https://tc39.es/ecma262/#sec-encode
// UNESCAPED is combined by ALWAYS_UNESCAPED and ";/?:@&=+$,#"
static UNESCAPED: LazyLock<UkeySet<u32>> = LazyLock::new(|| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ use derivative::Derivative;
use futures::future::join_all;
use rspack_core::{
rspack_sources::{BoxSource, MapOptions, RawSource, Source, SourceExt},
ApplyContext, BoxModule, ChunkInitFragments, ChunkUkey, Compilation, CompilationParams,
CompilerCompilation, CompilerOptions, ModuleIdentifier, Plugin, PluginContext,
ApplyContext, BoxModule, ChunkInitFragments, ChunkUkey, Compilation,
CompilationAdditionalTreeRuntimeRequirements, CompilationParams, CompilerCompilation,
CompilerOptions, ModuleIdentifier, Plugin, PluginContext, RuntimeGlobals,
};
use rspack_error::Result;
use rspack_hash::RspackHash;
Expand Down Expand Up @@ -173,9 +174,15 @@ fn eval_source_map_devtool_plugin_render_module_content(
let base64 = rspack_base64::encode_to_string(&map_buffer);
let footer =
format!("\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,{base64}");
let module_content =
simd_json::to_string(&format!("{source}{footer}")).expect("should convert to string");
RawSource::from(format!(
"eval({});",
simd_json::to_string(&format!("{source}{footer}")).expect("should convert to string")
if compilation.options.output.trusted_types.is_some() {
format!("{}({})", RuntimeGlobals::CREATE_SCRIPT, module_content)
} else {
module_content
}
))
.boxed()
};
Expand Down Expand Up @@ -205,6 +212,20 @@ fn eval_source_map_devtool_plugin_inline_in_runtime_bailout(
Ok(Some("the eval-source-map devtool is used.".to_string()))
}

#[plugin_hook(CompilationAdditionalTreeRuntimeRequirements for EvalSourceMapDevToolPlugin)]
async fn eval_source_map_devtool_plugin_additional_tree_runtime_requirements(
&self,
compilation: &mut Compilation,
_chunk_ukey: &ChunkUkey,
runtime_requirements: &mut RuntimeGlobals,
) -> Result<()> {
if compilation.options.output.trusted_types.is_some() {
runtime_requirements.insert(RuntimeGlobals::CREATE_SCRIPT);
}

Ok(())
}

#[async_trait::async_trait]
impl Plugin for EvalSourceMapDevToolPlugin {
fn name(&self) -> &'static str {
Expand All @@ -221,6 +242,11 @@ impl Plugin for EvalSourceMapDevToolPlugin {
.compiler_hooks
.compilation
.tap(eval_source_map_devtool_plugin_compilation::new(self));
ctx
.context
.compilation_hooks
.additional_tree_runtime_requirements
.tap(eval_source_map_devtool_plugin_additional_tree_runtime_requirements::new(self));
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use rspack_core::{
AsContextDependency, AsModuleDependency, Compilation, Dependency, DependencyCategory,
DependencyId, DependencyTemplate, DependencyType, RealDependencyLocation, RuntimeGlobals,
RuntimeSpec, TemplateContext, TemplateReplaceSource,
};

#[derive(Debug, Clone)]
pub struct CreateScriptUrlDependency {
id: DependencyId,
range: RealDependencyLocation,
range_path: (u32, u32),
}

impl CreateScriptUrlDependency {
pub fn new(range: RealDependencyLocation, range_path: (u32, u32)) -> Self {
Self {
id: DependencyId::new(),
range,
range_path,
}
}
}

impl Dependency for CreateScriptUrlDependency {
fn id(&self) -> &DependencyId {
&self.id
}

fn category(&self) -> &DependencyCategory {
&DependencyCategory::Worker
}

fn dependency_type(&self) -> &DependencyType {
&DependencyType::CreateScriptUrl
}

fn range(&self) -> Option<&RealDependencyLocation> {
Some(&self.range)
}

fn could_affect_referencing_module(&self) -> rspack_core::AffectType {
rspack_core::AffectType::False
}
}

impl DependencyTemplate for CreateScriptUrlDependency {
fn apply(
&self,
source: &mut TemplateReplaceSource,
code_generatable_context: &mut TemplateContext,
) {
code_generatable_context
.runtime_requirements
.insert(RuntimeGlobals::CREATE_SCRIPT_URL);

source.insert(
self.range_path.0,
format!("{}(", RuntimeGlobals::CREATE_SCRIPT_URL).as_str(),
None,
);
source.insert(self.range_path.1, ")", None);
}

fn dependency_id(&self) -> Option<DependencyId> {
Some(self.id)
}

fn update_hash(
&self,
_hasher: &mut dyn std::hash::Hasher,
_compilation: &Compilation,
_runtime: Option<&RuntimeSpec>,
) {
}
}

impl AsModuleDependency for CreateScriptUrlDependency {}
impl AsContextDependency for CreateScriptUrlDependency {}
2 changes: 2 additions & 0 deletions crates/rspack_plugin_javascript/src/dependency/worker/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod create_script_url_dependency;
pub use create_script_url_dependency::CreateScriptUrlDependency;
use rspack_core::{
get_chunk_from_ukey, AsContextDependency, Compilation, Dependency, DependencyCategory,
DependencyId, DependencyTemplate, DependencyType, ExtendedReferencedExport, ModuleDependency,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use super::{
JavascriptParserPlugin,
};
use crate::{
dependency::WorkerDependency,
dependency::{CreateScriptUrlDependency, WorkerDependency},
utils::object_properties::get_literal_str_by_obj_prop,
visitors::{JavascriptParser, TagInfoData},
webpack_comment::try_extract_webpack_magic_comment,
Expand Down Expand Up @@ -118,6 +118,16 @@ fn add_dependencies(
})));

parser.blocks.push(Box::new(block));

if parser.compiler_options.output.trusted_types.is_some() {
parser
.dependencies
.push(Box::new(CreateScriptUrlDependency::new(
span.into(),
parsed_path.range,
)));
}

if let Some(range) = range {
parser
.presentational_dependencies
Expand Down
46 changes: 46 additions & 0 deletions crates/rspack_plugin_runtime/src/runtime_module/create_script.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use rspack_collections::Identifier;
use rspack_core::{
impl_runtime_module,
rspack_sources::{BoxSource, RawSource, SourceExt},
Compilation, RuntimeGlobals, RuntimeModule,
};

#[impl_runtime_module]
#[derive(Debug)]
pub struct CreateScriptRuntimeModule {
id: Identifier,
}

impl Default for CreateScriptRuntimeModule {
fn default() -> Self {
Self::with_default(Identifier::from("webpack/runtime/create_script"))
}
}

impl RuntimeModule for CreateScriptRuntimeModule {
fn name(&self) -> Identifier {
self.id
}

fn generate(&self, compilation: &Compilation) -> rspack_error::Result<BoxSource> {
Ok(
RawSource::from(format!(
r#"
{} = function(script){{
return {};
}};
"#,
RuntimeGlobals::CREATE_SCRIPT,
if compilation.options.output.trusted_types.is_some() {
format!(
"{}().createScript(script)",
RuntimeGlobals::GET_TRUSTED_TYPES_POLICY
)
} else {
"script".to_string()
}
))
.boxed(),
)
}
}
2 changes: 2 additions & 0 deletions crates/rspack_plugin_runtime/src/runtime_module/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod chunk_prefetch_trigger;
mod chunk_preload_trigger;
mod compat_get_default_export;
mod create_fake_namespace_object;
mod create_script;
mod create_script_url;
mod define_property_getters;
mod ensure_chunk;
Expand Down Expand Up @@ -49,6 +50,7 @@ pub use chunk_prefetch_trigger::ChunkPrefetchTriggerRuntimeModule;
pub use chunk_preload_trigger::ChunkPreloadTriggerRuntimeModule;
pub use compat_get_default_export::CompatGetDefaultExportRuntimeModule;
pub use create_fake_namespace_object::CreateFakeNamespaceObjectRuntimeModule;
pub use create_script::CreateScriptRuntimeModule;
pub use create_script_url::CreateScriptUrlRuntimeModule;
pub use define_property_getters::DefinePropertyGettersRuntimeModule;
pub use ensure_chunk::EnsureChunkRuntimeModule;
Expand Down
17 changes: 10 additions & 7 deletions crates/rspack_plugin_runtime/src/runtime_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ use crate::runtime_module::{
chunk_has_css, is_enabled_for_chunk, AsyncRuntimeModule, AutoPublicPathRuntimeModule,
BaseUriRuntimeModule, ChunkNameRuntimeModule, ChunkPrefetchPreloadFunctionRuntimeModule,
CompatGetDefaultExportRuntimeModule, CreateFakeNamespaceObjectRuntimeModule,
CreateScriptUrlRuntimeModule, DefinePropertyGettersRuntimeModule, EnsureChunkRuntimeModule,
GetChunkFilenameRuntimeModule, GetChunkUpdateFilenameRuntimeModule, GetFullHashRuntimeModule,
GetMainFilenameRuntimeModule, GetTrustedTypesPolicyRuntimeModule, GlobalRuntimeModule,
HarmonyModuleDecoratorRuntimeModule, HasOwnPropertyRuntimeModule, LoadScriptRuntimeModule,
MakeNamespaceObjectRuntimeModule, NodeModuleDecoratorRuntimeModule, NonceRuntimeModule,
OnChunkLoadedRuntimeModule, PublicPathRuntimeModule, RelativeUrlRuntimeModule,
RuntimeIdRuntimeModule, SystemContextRuntimeModule,
CreateScriptRuntimeModule, CreateScriptUrlRuntimeModule, DefinePropertyGettersRuntimeModule,
EnsureChunkRuntimeModule, GetChunkFilenameRuntimeModule, GetChunkUpdateFilenameRuntimeModule,
GetFullHashRuntimeModule, GetMainFilenameRuntimeModule, GetTrustedTypesPolicyRuntimeModule,
GlobalRuntimeModule, HarmonyModuleDecoratorRuntimeModule, HasOwnPropertyRuntimeModule,
LoadScriptRuntimeModule, MakeNamespaceObjectRuntimeModule, NodeModuleDecoratorRuntimeModule,
NonceRuntimeModule, OnChunkLoadedRuntimeModule, PublicPathRuntimeModule,
RelativeUrlRuntimeModule, RuntimeIdRuntimeModule, SystemContextRuntimeModule,
};

static GLOBALS_ON_REQUIRE: LazyLock<Vec<RuntimeGlobals>> = LazyLock::new(|| {
Expand Down Expand Up @@ -407,6 +407,9 @@ fn runtime_requirements_in_tree(
compilation
.add_runtime_module(chunk_ukey, CreateScriptUrlRuntimeModule::default().boxed())?;
}
RuntimeGlobals::CREATE_SCRIPT => {
compilation.add_runtime_module(chunk_ukey, CreateScriptRuntimeModule::default().boxed())?;
}
RuntimeGlobals::ON_CHUNKS_LOADED => {
compilation
.add_runtime_module(chunk_ukey, OnChunkLoadedRuntimeModule::default().boxed())?;
Expand Down
Loading

2 comments on commit f6f1798

@rspack-bot
Copy link

Choose a reason for hiding this comment

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

📝 Benchmark detail: Open

Name Base (2024-09-12 b1bf153) Current Change
10000_development-mode + exec 2.25 s ± 51 ms 2.25 s ± 44 ms +0.22 %
10000_development-mode_hmr + exec 724 ms ± 4.9 ms 723 ms ± 4.7 ms -0.10 %
10000_production-mode + exec 2.84 s ± 49 ms 2.83 s ± 39 ms -0.29 %
arco-pro_development-mode + exec 1.84 s ± 71 ms 1.84 s ± 52 ms -0.04 %
arco-pro_development-mode_hmr + exec 434 ms ± 1.5 ms 435 ms ± 3.4 ms +0.34 %
arco-pro_production-mode + exec 3.24 s ± 86 ms 3.26 s ± 76 ms +0.61 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 3.31 s ± 72 ms 3.35 s ± 78 ms +1.45 %
threejs_development-mode_10x + exec 1.68 s ± 11 ms 1.68 s ± 13 ms -0.55 %
threejs_development-mode_10x_hmr + exec 807 ms ± 15 ms 804 ms ± 7.6 ms -0.36 %
threejs_production-mode_10x + exec 5.14 s ± 42 ms 5.17 s ± 35 ms +0.57 %

@rspack-bot
Copy link

Choose a reason for hiding this comment

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

📝 Ran ecosystem CI: Open

suite result
modernjs ✅ success
_selftest ✅ success
nx ❌ failure
rspress ✅ success
rslib ❌ failure
rsbuild ❌ failure
examples ✅ success

Please sign in to comment.