Skip to content

Commit

Permalink
fix: plugin circle call & dynamic import (#1901)
Browse files Browse the repository at this point in the history
fix: fix plugin circle call between Runtime & LazyCompilation, fix runtime & lazyCompilation conflict
  • Loading branch information
shulandmimi authored Oct 31, 2024
1 parent 676f429 commit 3ae860b
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/happy-mice-visit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@farmfe/core": patch
---

fix plugin circle call between Runtime & LazyCompilation, fix runtime & lazyCompilation conflict
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"lazyCompilation": true,
"output": {
"targetEnv": "browser"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

export const name = 'foo';
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//index.js:
window['__farm_default_namespace__'] = {__FARM_TARGET_ENV__: 'browser'};function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}function _export_star(from, to) {
Object.keys(from).forEach(function(k) {
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
Object.defineProperty(to, k, {
enumerable: true,
get: function() {
return from[k];
}
});
}
});
return from;
}function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) return obj;
if (obj === null || typeof obj !== "object" && typeof obj !== "function") return {
default: obj
};
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) return cache.get(obj);
var newObj = {
__proto__: null
};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) Object.defineProperty(newObj, key, desc);
else newObj[key] = obj[key];
}
}
newObj.default = obj;
if (cache) cache.set(obj, newObj);
return newObj;
}function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}((function(){const name = 'foo';
var foo_ts_ns = {
name: name,
__esModule: true
};

Promise.resolve(foo_ts_ns).then((res)=>{
console.log(res);
});
window['__farm_default_namespace__'].__farm_module_system__.setPlugins([]);
})());(function(_){for(var r in _){_[r].__farm_resource_pot__='index_dcdc.js';window['__farm_default_namespace__'].__farm_module_system__.register(r,_[r])}})({"b5d64806":function (module, exports, farmRequire, farmDynamicRequire) {}
,});window['__farm_default_namespace__'].__farm_module_system__.setInitialLoadedResources([]);window['__farm_default_namespace__'].__farm_module_system__.setDynamicModuleResourcesMap([],{ });var farmModuleSystem = window['__farm_default_namespace__'].__farm_module_system__;farmModuleSystem.bootstrap();var entry = farmModuleSystem.require("b5d64806");
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

/// @ts-ignore
import('./foo.ts').then(res => {
console.log(res);
})
5 changes: 5 additions & 0 deletions crates/compiler/tests/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ fn test(file: String, crate_path: String) {
}];

if let Some(config_from_file) = config_from_file {
// TODO: macro
if let Some(mode) = get_config_field(&config_from_file, &["mode"]) {
config.mode = mode;
}
Expand All @@ -64,6 +65,10 @@ fn test(file: String, crate_path: String) {
if let Some(target_env) = get_config_field(&config_from_file, &["output", "targetEnv"]) {
config.output.target_env = target_env;
}

if let Some(lazy_compilation) = get_config_field(&config_from_file, &["lazyCompilation"]) {
config.lazy_compilation = lazy_compilation;
}
}

(config, plugins)
Expand Down
20 changes: 20 additions & 0 deletions crates/core/src/plugin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,26 @@ pub struct PluginHookContext {
pub meta: HashMap<String, String>,
}

impl PluginHookContext {
fn caller_format<T: AsRef<str>>(name: T) -> String {
format!("[{}]", name.as_ref())
}

pub fn add_caller<T: AsRef<str>>(&self, name: T) -> Option<String> {
match self.caller.as_ref() {
Some(c) => Some(format!("{}{}", c, Self::caller_format(name))),
None => Some(Self::caller_format(name)),
}
}
pub fn contain_caller<T: AsRef<str>>(&self, name: T) -> bool {
if let Some(ref s) = self.caller {
s.contains(&Self::caller_format(name))
} else {
false
}
}
}

/// Parameter of the resolve hook
#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
Expand Down
34 changes: 20 additions & 14 deletions crates/plugin_lazy_compilation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use farmfe_core::{
module::{ModuleId, ModuleType},
plugin::{Plugin, PluginHookContext, PluginLoadHookResult, PluginResolveHookParam, ResolveKind},
};
use farmfe_toolkit::html::get_farm_global_this;
use farmfe_toolkit::{html::get_farm_global_this, script::constant::RUNTIME_SUFFIX};
use farmfe_utils::{relative, stringify_query};

pub const DYNAMIC_VIRTUAL_SUFFIX: &str = ".farm_dynamic_import_virtual_module";
Expand All @@ -19,9 +19,11 @@ impl FarmPluginLazyCompilation {
}
}

const PLUGIN_NAME: &str = "FarmPluginLazyCompilation";

impl Plugin for FarmPluginLazyCompilation {
fn name(&self) -> &str {
"FarmPluginLazyCompilation"
PLUGIN_NAME
}

/// The lazy compilation plugin should take priority of all other plugins
Expand All @@ -35,10 +37,16 @@ impl Plugin for FarmPluginLazyCompilation {
context: &std::sync::Arc<farmfe_core::context::CompilationContext>,
hook_context: &PluginHookContext,
) -> farmfe_core::error::Result<Option<farmfe_core::plugin::PluginResolveHookResult>> {
if let Some(caller) = &hook_context.caller {
if caller == "FarmPluginLazyCompilation" {
return Ok(None);
}
if hook_context.contain_caller(PLUGIN_NAME)
// All runtime files will be merged into one resourcePot, even files introduced through `import()`
// Therefore, the asynchronous polyfill here is unnecessary
|| param.source.ends_with(RUNTIME_SUFFIX)
|| param
.importer
.as_ref()
.is_some_and(|i| i.to_string().ends_with(RUNTIME_SUFFIX))
{
return Ok(None);
}

// If importer is a dynamic virtual module, we should resolve the dependency using the original importer
Expand All @@ -52,7 +60,7 @@ impl Plugin for FarmPluginLazyCompilation {
},
context,
&PluginHookContext {
caller: Some("FarmPluginLazyCompilation".to_string()),
caller: hook_context.add_caller(PLUGIN_NAME),
..hook_context.clone()
},
)? {
Expand Down Expand Up @@ -81,7 +89,7 @@ impl Plugin for FarmPluginLazyCompilation {
},
context,
&PluginHookContext {
caller: Some("FarmPluginLazyCompilation".to_string()),
caller: hook_context.add_caller(PLUGIN_NAME),
..hook_context.clone()
},
)?;
Expand Down Expand Up @@ -118,7 +126,7 @@ impl Plugin for FarmPluginLazyCompilation {
param,
context,
&PluginHookContext {
caller: Some("FarmPluginLazyCompilation".to_string()),
caller: hook_context.add_caller(PLUGIN_NAME),
..hook_context.clone()
},
)?;
Expand All @@ -143,12 +151,10 @@ impl Plugin for FarmPluginLazyCompilation {
&self,
param: &farmfe_core::plugin::PluginLoadHookParam,
context: &std::sync::Arc<farmfe_core::context::CompilationContext>,
_hook_context: &farmfe_core::plugin::PluginHookContext,
hook_context: &farmfe_core::plugin::PluginHookContext,
) -> farmfe_core::error::Result<Option<farmfe_core::plugin::PluginLoadHookResult>> {
if let Some(caller) = &_hook_context.caller {
if caller == "FarmPluginLazyCompilation" {
return Ok(None);
}
if hook_context.contain_caller(PLUGIN_NAME) {
return Ok(None);
}

if param.resolved_path.ends_with(DYNAMIC_VIRTUAL_SUFFIX) {
Expand Down
10 changes: 6 additions & 4 deletions crates/plugin_runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ use farmfe_toolkit::{
use insert_runtime_plugins::insert_runtime_plugins;
use render_resource_pot::*;

pub const RUNTIME_SUFFIX: &str = ".farm-runtime";
pub use farmfe_toolkit::script::constant::RUNTIME_SUFFIX;
pub const ASYNC_MODULES: &str = "async_modules";

mod find_async_modules;
mod handle_entry_resources;
mod insert_runtime_plugins;
pub mod render_resource_pot;

const PLUGIN_NAME: &str = "FarmPluginRuntime";
/// FarmPluginRuntime is charge of:
/// * resolving, parsing and generating a executable runtime code and inject the code into the entries.
/// * merge module's ast and render the script module using farm runtime's specification, for example, wrap the module to something like `function(module, exports, require) { xxx }`, see [Farm Runtime RFC](https://github.com/farm-fe/rfcs/pull/1)
Expand All @@ -55,7 +57,7 @@ pub struct FarmPluginRuntime {}

impl Plugin for FarmPluginRuntime {
fn name(&self) -> &str {
"FarmPluginRuntime"
PLUGIN_NAME
}

fn config(&self, config: &mut Config) -> farmfe_core::error::Result<Option<()>> {
Expand Down Expand Up @@ -103,7 +105,7 @@ impl Plugin for FarmPluginRuntime {
hook_context: &PluginHookContext,
) -> farmfe_core::error::Result<Option<PluginResolveHookResult>> {
// avoid cyclic resolve
if matches!(&hook_context.caller, Some(c) if c == "FarmPluginRuntime") {
if hook_context.contain_caller(PLUGIN_NAME) {
Ok(None)
} else if param.source.ends_with(RUNTIME_SUFFIX) // if the source is a runtime module or its importer is a runtime module, then resolve it to the runtime module
|| (param.importer.is_some()
Expand All @@ -122,7 +124,7 @@ impl Plugin for FarmPluginRuntime {
},
context,
&PluginHookContext {
caller: Some(String::from("FarmPluginRuntime")),
caller: hook_context.add_caller(PLUGIN_NAME),
meta: HashMap::new(),
},
)?;
Expand Down
1 change: 1 addition & 0 deletions crates/toolkit/src/script/constant.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub const RUNTIME_SUFFIX: &str = ".farm-runtime";
1 change: 1 addition & 0 deletions crates/toolkit/src/script/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use self::swc_try_with::try_with;

pub mod defined_idents_collector;
pub mod swc_try_with;
pub mod constant;

/// parse the content of a module to [SwcModule] ast.
pub fn parse_module(
Expand Down

0 comments on commit 3ae860b

Please sign in to comment.