Skip to content

Commit

Permalink
fix: fix additional_data for css extract plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
h-a-n-a committed Apr 18, 2024
1 parent acd03c8 commit 9207a0b
Show file tree
Hide file tree
Showing 11 changed files with 185 additions and 57 deletions.
2 changes: 1 addition & 1 deletion crates/node_binding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl Rspack {
let js_plugin = JsHooksAdapterPlugin::from_js_hooks(env, register_js_taps)?;
plugins.push(js_plugin.clone().boxed());
for bp in builtin_plugins {
bp.append_to(&mut plugins)
bp.append_to(env, &mut plugins)
.map_err(|e| Error::from_reason(format!("{e}")))?;
}

Expand Down
1 change: 1 addition & 0 deletions crates/rspack_binding_options/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![feature(try_blocks)]
#![feature(let_chains)]
mod options;
mod plugins;
pub use options::*;
13 changes: 8 additions & 5 deletions crates/rspack_binding_options/src/options/raw_builtins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mod raw_progress;
mod raw_swc_js_minimizer;
mod raw_to_be_deprecated;

use napi::{bindgen_prelude::FromNapiValue, JsUnknown};
use napi::{bindgen_prelude::FromNapiValue, Env, JsUnknown};
use napi_derive::napi;
use rspack_core::{BoxPlugin, Define, DefinePlugin, PluginExt, Provide, ProvidePlugin};
use rspack_error::Result;
Expand Down Expand Up @@ -77,9 +77,10 @@ use self::{
raw_mf::{RawConsumeSharedPluginOptions, RawContainerReferencePluginOptions, RawProvideOptions},
};
use crate::{
plugins::JsLoaderResolverPlugin, JsLoaderRunner, RawEntryPluginOptions,
RawEvalDevToolModulePluginOptions, RawExternalItemWrapper, RawExternalsPluginOptions,
RawHttpExternalsRspackPluginOptions, RawSourceMapDevToolPluginOptions, RawSplitChunksOptions,
plugins::{CssExtractRspackAdditionalDataPlugin, JsLoaderResolverPlugin},
JsLoaderRunner, RawEntryPluginOptions, RawEvalDevToolModulePluginOptions, RawExternalItemWrapper,
RawExternalsPluginOptions, RawHttpExternalsRspackPluginOptions, RawSourceMapDevToolPluginOptions,
RawSplitChunksOptions,
};

#[napi(string_enum)]
Expand Down Expand Up @@ -163,7 +164,7 @@ pub struct BuiltinPlugin {
}

impl BuiltinPlugin {
pub fn append_to(self, plugins: &mut Vec<BoxPlugin>) -> rspack_error::Result<()> {
pub fn append_to(self, env: Env, plugins: &mut Vec<BoxPlugin>) -> rspack_error::Result<()> {
match self.name {
// webpack also have these plugins
BuiltinPluginName::DefinePlugin => {
Expand Down Expand Up @@ -420,6 +421,8 @@ impl BuiltinPlugin {
)
}
BuiltinPluginName::CssExtractRspackPlugin => {
let additional_data_plugin = CssExtractRspackAdditionalDataPlugin::new(env)?.boxed();
plugins.push(additional_data_plugin);
let plugin = rspack_plugin_extract_css::plugin::PluginCssExtract::new(
downcast_into::<RawCssExtractPluginOption>(self.options)?.into(),
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use std::fmt::Debug;

use napi::{bindgen_prelude::Unknown, Env};
use rspack_core::{
ApplyContext, CompilerOptions, NormalModuleAdditionalData, Plugin, PluginContext,
};
use rspack_error::Result;
use rspack_hook::{plugin, plugin_hook};
use rspack_loader_runner::AdditionalData;
use rspack_napi::{threadsafe_js_value_ref::ThreadsafeJsValueRef, JsCallback, NapiResultExt};
use rspack_plugin_extract_css::{CssExtractJsonData, CssExtractJsonDataList};
use tokio::sync::oneshot;

#[plugin]
pub(crate) struct CssExtractRspackAdditionalDataPlugin {
js_callback: JsCallback<Box<dyn FnOnce(Env) + Sync>>,
}

impl CssExtractRspackAdditionalDataPlugin {
pub fn new(env: Env) -> Result<Self> {
Ok(Self::new_inner(
JsCallback::new(env.raw()).into_rspack_result()?,
))
}
}

impl Debug for CssExtractRspackAdditionalDataPlugin {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "CssExtractRspackAdditionalDataPlugin(..)")
}
}

#[plugin_hook(NormalModuleAdditionalData for CssExtractRspackAdditionalDataPlugin)]
async fn additional_data(&self, additional_data: &mut AdditionalData) -> Result<()> {
if !additional_data.contains::<ThreadsafeJsValueRef<Unknown>>() {
return Ok(());
}
let (tx, rx) = oneshot::channel::<AdditionalData>();
let mut old_data = std::mem::take(additional_data);
self.js_callback.call(Box::new(move |env| {
if let Some(data) = old_data.get::<ThreadsafeJsValueRef<Unknown>>()
&& let Ok(data) = data.get(env)
&& let Ok(data) = data.coerce_to_object()
&& let Ok(Some(data)) = data.get::<_, String>("css-extract-rspack-plugin")
{
let mut list = data.split("__RSPACK_CSS_EXTRACT_SEP__");
let mut data_list = vec![];
while let Some(identifier) = list.next() {
#[allow(clippy::unwrap_in_result)]
{
// parse the css data from js loader
// data:
// [identifier]__RSPACK_CSS_EXTRACT_SEP__
// [content]__RSPACK_CSS_EXTRACT_SEP__
// [context]__RSPACK_CSS_EXTRACT_SEP__
// [media]__RSPACK_CSS_EXTRACT_SEP__
// [supports]__RSPACK_CSS_EXTRACT_SEP__
// [sourceMap]__RSPACK_CSS_EXTRACT_SEP__
// [identifier]__RSPACK_CSS_EXTRACT_SEP__ ... repeated
// [content]__RSPACK_CSS_EXTRACT_SEP__
data_list.push(CssExtractJsonData {
identifier: identifier.into(),
content: list.next().unwrap().into(),
context: list.next().unwrap().into(),
media: list.next().unwrap().into(),
supports: list.next().unwrap().into(),
source_map: list.next().unwrap().into(),
identifier_index: list
.next()
.unwrap()
.parse()
.expect("Cannot parse identifier_index, this should never happen"),
filepath: list.next().unwrap().into(),
});
}
}
old_data.insert(CssExtractJsonDataList(data_list));
};
tx.send(old_data)
.expect("should send `additional_data` for `CssExtractRspackAdditionalDataPlugin`");
}));
let new_data = rx
.await
.expect("should receive `additional_data` for `CssExtractRspackAdditionalDataPlugin`");
// ignore the default value here
let _ = std::mem::replace(additional_data, new_data);
Ok(())
}

#[async_trait::async_trait]
impl Plugin for CssExtractRspackAdditionalDataPlugin {
fn name(&self) -> &'static str {
"CssExtractRspackAdditionalDataPlugin"
}

fn apply(
&self,
ctx: PluginContext<&mut ApplyContext>,
_options: &mut CompilerOptions,
) -> Result<()> {
ctx
.context
.normal_module_hooks
.additional_data
.tap(additional_data::new(self));
Ok(())
}
}
2 changes: 2 additions & 0 deletions crates/rspack_binding_options/src/plugins/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
mod css_extract_additional_data;
mod js_loader_resolver;
pub(super) use css_extract_additional_data::CssExtractRspackAdditionalDataPlugin;
pub(super) use js_loader_resolver::JsLoaderResolverPlugin;
10 changes: 9 additions & 1 deletion crates/rspack_core/src/normal_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,14 @@ impl ModuleIssuer {
define_hook!(NormalModuleReadResource: AsyncSeriesBail(resource_data: &mut ResourceData) -> Content);
define_hook!(NormalModuleLoader: SyncSeries(loader_context: &mut LoaderContext<CompilerContext>));
define_hook!(NormalModuleBeforeLoaders: SyncSeries(module: &mut NormalModule));
define_hook!(NormalModuleAdditionalData: AsyncSeries(additional_data: &mut AdditionalData));

#[derive(Debug, Default)]
pub struct NormalModuleHooks {
pub read_resource: NormalModuleReadResourceHook,
pub loader: NormalModuleLoaderHook,
pub before_loaders: NormalModuleBeforeLoadersHook,
pub additional_data: NormalModuleAdditionalDataHook,
}

#[impl_source_map_config]
Expand Down Expand Up @@ -411,7 +413,7 @@ impl Module for NormalModule {
additional_data,
)
.await;
let (loader_result, ds) = match loader_result {
let (mut loader_result, ds) = match loader_result {
Ok(r) => r.split_into_parts(),
Err(e) => {
let mut e = ModuleBuildError(e).boxed();
Expand Down Expand Up @@ -441,6 +443,12 @@ impl Module for NormalModule {
});
}
};
build_context
.plugin_driver
.normal_module_hooks
.additional_data
.call(&mut loader_result.additional_data)
.await?;
self.add_diagnostics(ds);

let content = if self.module_type().is_binary() {
Expand Down
2 changes: 1 addition & 1 deletion crates/rspack_loader_runner/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ impl<C> TryFrom<LoaderContext<'_, C>> for TWithDiagnosticArray<LoaderResult> {
}
}

pub async fn run_loaders<C: Send>(
pub async fn run_loaders<C: 'static + Send>(
loaders: &[Arc<dyn Loader<C>>],
resource_data: &mut ResourceData,
plugins: &[&dyn LoaderRunnerPlugin<Context = C>],
Expand Down
2 changes: 1 addition & 1 deletion crates/rspack_napi/src/callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub struct JsCallback<Resolver: FnOnce(Env)> {
unsafe impl<Resolver: FnOnce(Env)> Send for JsCallback<Resolver> {}

impl<Resolver: FnOnce(Env)> JsCallback<Resolver> {
pub(crate) fn new(env: sys::napi_env) -> Result<Self> {
pub fn new(env: sys::napi_env) -> Result<Self> {
let mut async_resource_name = ptr::null_mut();
let s = unsafe { CStr::from_bytes_with_nul_unchecked(b"napi_js_callback\0") };
check_status!(
Expand Down
2 changes: 1 addition & 1 deletion crates/rspack_napi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod errors;
pub use errors::{NapiErrorExt, NapiResultExt};

mod callback;
pub(crate) use callback::JsCallback;
pub use callback::JsCallback;

pub mod threadsafe_function;
pub mod threadsafe_js_value_ref;
Expand Down
1 change: 1 addition & 0 deletions crates/rspack_plugin_extract_css/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
pub mod css_dependency;
mod css_module;
mod parser_and_generator;
pub use parser_and_generator::{CssExtractJsonData, CssExtractJsonDataList};
pub mod plugin;
mod runtime;
99 changes: 52 additions & 47 deletions crates/rspack_plugin_extract_css/src/parser_and_generator.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
use std::path::PathBuf;

use rspack_core::{ChunkGraph, Dependency, Module, ModuleGraph, ParserAndGenerator};
use rspack_error::TWithDiagnosticArray;
use rustc_hash::FxHashMap;
use serde::Deserialize;

use crate::css_dependency::CssDependency;

#[derive(Deserialize)]
struct CssExtractJsonData {
#[serde(rename = "css-extract-rspack-plugin")]
value: String,
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CssExtractJsonData {
pub identifier: String,
pub content: String,
pub context: String,
pub media: String,
pub supports: String,
pub source_map: String,
pub identifier_index: u32,
pub filepath: PathBuf,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CssExtractJsonDataList(pub Vec<CssExtractJsonData>);

#[derive(Debug)]
pub(crate) struct CssExtractParserAndGenerator {
orig_parser_generator: Box<dyn ParserAndGenerator>,
#[allow(clippy::vec_box)]
cache: FxHashMap<String, Vec<Box<CssDependency>>>,
cache: FxHashMap<CssExtractJsonDataList, Vec<Box<CssDependency>>>,
}

impl CssExtractParserAndGenerator {
Expand Down Expand Up @@ -46,51 +56,46 @@ impl ParserAndGenerator for CssExtractParserAndGenerator {
&mut self,
parse_context: rspack_core::ParseContext,
) -> rspack_error::Result<rspack_error::TWithDiagnosticArray<rspack_core::ParseResult>> {
let deps = if let Some(additional_data) = parse_context.additional_data.get::<String>() {
let deps = if let Some(additional_data) = parse_context
.additional_data
.get::<CssExtractJsonDataList>()
{
if let Some(deps) = self.cache.get(additional_data) {
deps.clone()
} else if let Ok(data) = serde_json::from_str::<CssExtractJsonData>(additional_data) {
// parse the css data from js loader
// data:
// [identifier]__RSPACK_CSS_EXTRACT_SEP__
// [content]__RSPACK_CSS_EXTRACT_SEP__
// [context]__RSPACK_CSS_EXTRACT_SEP__
// [media]__RSPACK_CSS_EXTRACT_SEP__
// [supports]__RSPACK_CSS_EXTRACT_SEP__
// [sourceMap]__RSPACK_CSS_EXTRACT_SEP__
// [identifier]__RSPACK_CSS_EXTRACT_SEP__ ... repeated
// [content]__RSPACK_CSS_EXTRACT_SEP__
let mut list = data.value.split("__RSPACK_CSS_EXTRACT_SEP__");

let mut deps = vec![];
} else {
let mut idx = 0;
while let Some(identifier) = list.next() {
#[allow(clippy::unwrap_in_result)]
{
deps.push(Box::new(CssDependency::new(
identifier.into(),
list.next().unwrap().into(),
list.next().unwrap().into(),
list.next().unwrap().into(),
list.next().unwrap().into(),
list.next().unwrap().into(),
list
.next()
.unwrap()
.parse()
.expect("Cannot parse identifier_index, this should never happen"),
idx,
list.next().unwrap().into(),
)));
}
idx += 1;
}

self.cache.insert(data.value.clone(), deps.clone());

let deps = additional_data
.0
.iter()
.map(
|CssExtractJsonData {
identifier,
content,
context,
media,
supports,
source_map,
identifier_index,
filepath,
}| {
let dep = Box::new(CssDependency::new(
identifier.into(),
content.clone(),
context.clone(),
media.clone(),
supports.clone(),
source_map.clone(),
*identifier_index,
idx,
filepath.clone(),
));
idx += 1;
dep
},
)
.collect::<Vec<_>>();
self.cache.insert(additional_data.clone(), deps.clone());
deps
} else {
vec![]
}
} else {
vec![]
Expand Down

0 comments on commit 9207a0b

Please sign in to comment.